diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2008-10-07 13:32:32 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2008-10-07 13:32:32 (GMT) |
commit | bdbdbb9f89db8d3a76fc71705cdbbd89124f4687 (patch) | |
tree | 53d16d2097c591d2c7094da6b8e2b23ef5663a0f | |
parent | b256db872d5ce4f81c6486b60c4e29e8122b67c2 (diff) | |
download | hdf5-bdbdbb9f89db8d3a76fc71705cdbbd89124f4687.zip hdf5-bdbdbb9f89db8d3a76fc71705cdbbd89124f4687.tar.gz hdf5-bdbdbb9f89db8d3a76fc71705cdbbd89124f4687.tar.bz2 |
[svn-r15801] Description:
Bring r15800 back from trunk:
- File free space branch changes through r15794
Tested on:
Mac OS X/32 10.5.5 (amazon) in debug mode
Mac OS X/32 10.5.5 (amazon) w/C++ & FORTRAN, w/threadsafe,
in production mode
FreeBSD/32 6.3 (duty) in debug mode
FreeBSD/64 6.3 (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/Intel compilers w/default API=1.6.x,
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.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
in production mode
Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode
Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode
119 files changed, 17924 insertions, 6373 deletions
@@ -499,9 +499,13 @@ ./src/H5Epublic.h ./src/H5Eterm.h ./src/H5F.c +./src/H5Faccum.c ./src/H5Fdbg.c ./src/H5Ffake.c +./src/H5Fio.c ./src/H5Fmount.c +./src/H5Fmpi.c +./src/H5Fquery.c ./src/H5Fsfile.c ./src/H5Fsuper.c ./src/H5Fpkg.h @@ -515,6 +519,7 @@ ./src/H5FDdirect.h ./src/H5FDfamily.c ./src/H5FDfamily.h +./src/H5FDint.c ./src/H5FDlog.c ./src/H5FDlog.h ./src/H5FDmpi.c @@ -542,12 +547,15 @@ ./src/H5FS.c ./src/H5FScache.c ./src/H5FSdbg.c +./src/H5FStest.c +./src/H5FSstat.c ./src/H5FSpkg.h ./src/H5FSprivate.h ./src/H5FSpublic.h ./src/H5FSsection.c ./src/H5G.c ./src/H5Gbtree2.c +./src/H5Gcache.c ./src/H5Gcompact.c ./src/H5Gdense.c ./src/H5Gdeprec.c @@ -585,11 +593,13 @@ ./src/H5HFtest.c ./src/H5HFtiny.c ./src/H5HG.c +./src/H5HGcache.c ./src/H5HGdbg.c ./src/H5HGpkg.h ./src/H5HGprivate.h ./src/H5HGpublic.h ./src/H5HL.c +./src/H5HLcache.c ./src/H5HLdbg.c ./src/H5HLpkg.h ./src/H5HLprivate.h @@ -606,6 +616,10 @@ ./src/H5Lprivate.h ./src/H5Lpublic.h ./src/H5MF.c +./src/H5MFaggr.c +./src/H5MFdbg.c +./src/H5MFsection.c +./src/H5MFpkg.h ./src/H5MFprivate.h ./src/H5MM.c ./src/H5MMprivate.h @@ -780,6 +794,7 @@ ./test/family_v16_00002.h5 ./test/family_v16_00003.h5 ./test/fheap.c +./test/freespace.c ./test/fill_old.h5 ./test/fillval.c ./test/flush1.c @@ -814,6 +829,7 @@ ./test/lheap.c ./test/links.c ./test/mergemsg.h5 +./test/mf.c ./test/mount.c ./test/mtime.c ./test/noencoder.h5 diff --git a/c++/test/dsets.cpp b/c++/test/dsets.cpp index 603a0aa..319f894 100644 --- a/c++/test/dsets.cpp +++ b/c++/test/dsets.cpp @@ -413,8 +413,10 @@ filter_bogus(unsigned int flags, size_t cd_nelmts, static herr_t test_compression(H5File& file) { +#ifndef H5_HAVE_FILTER_DEFLATE const char *not_supported; not_supported = " Deflate compression is not enabled."; +#endif /* H5_HAVE_FILTER_DEFLATE */ int points[100][200]; int check[100][200]; hsize_t i, j, n; @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Id: configure.in 15725 2008-09-30 16:36:29Z brtnfld . +# From configure.in Id: configure.in 15781 2008-10-06 03:11:40Z hdftest . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for HDF5 1.8.1-snap7. # diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index c0bd71f..144df7c 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -63,6 +63,7 @@ New Features Library ------- + - Improved free space tracking in file to be faster. (QAK - 2008/10/06) - Added 'mounted' field to H5G_info_t struct. (QAK - 2008/07/15) Parallel Library @@ -109,6 +110,8 @@ Bug Fixes since HDF5-1.8.1 Library ------- + - Corrected alignment+threshold errors to work correctly when metadata + aggregation is enabled. (QAK - 2008/10/06) - Changed H5Fget_obj_count and H5Fget_obj_ids to ignore objects registered by the library for internal library use. (NAF - 2008/10/06) @@ -831,7 +831,9 @@ done: * * Modifications: * - * None. + * Added 'flags' paramater, to allow freeing file space + * + * QAK - 2/5/08 * *------------------------------------------------------------------------- */ @@ -839,15 +841,16 @@ herr_t H5AC_expunge_entry(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, - haddr_t addr) + haddr_t addr, + unsigned flags) { herr_t result; - herr_t ret_value=SUCCEED; /* Return value */ H5AC_t * cache_ptr = NULL; #if H5AC__TRACE_FILE_ENABLED char trace[128] = ""; FILE * trace_file_ptr = NULL; #endif /* H5AC__TRACE_FILE_ENABLED */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5AC_expunge_entry, FAIL) @@ -881,7 +884,8 @@ H5AC_expunge_entry(H5F_t *f, H5AC_noblock_dxpl_id, cache_ptr, type, - addr); + addr, + flags); if ( result < 0 ) { @@ -1280,6 +1284,10 @@ H5AC_set(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, void * HDassert(H5F_addr_defined(addr)); HDassert(thing); + /* Check for invalid access request */ + if(0 == (f->intent & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "no write intent on file") + #if H5AC__TRACE_FILE_ENABLED /* For the insert, only the addr, size, type id and flags are really * necessary in the trace file. Write the result to catch occult diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index bbbcf11..2b2c106 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -249,6 +249,8 @@ extern hid_t H5AC_ind_dxpl_id; #define H5AC__FLUSH_CLEAR_ONLY_FLAG H5C__FLUSH_CLEAR_ONLY_FLAG #define H5AC__FLUSH_MARKED_ENTRIES_FLAG H5C__FLUSH_MARKED_ENTRIES_FLAG #define H5AC__FLUSH_IGNORE_PROTECTED_FLAG H5C__FLUSH_IGNORE_PROTECTED_FLAG +#define H5AC__FREE_FILE_SPACE_FLAG H5C__FREE_FILE_SPACE_FLAG +#define H5AC__TAKE_OWNERSHIP_FLAG H5C__TAKE_OWNERSHIP_FLAG /* #defines of flags used to report entry status in the @@ -294,7 +296,8 @@ H5_DLL herr_t H5AC_rename(H5F_t *f, const H5AC_class_t *type, H5_DLL herr_t H5AC_dest(H5F_t *f, hid_t dxpl_id); H5_DLL herr_t H5AC_expunge_entry(H5F_t *f, hid_t dxpl_id, - const H5AC_class_t *type, haddr_t addr); + const H5AC_class_t *type, haddr_t addr, + unsigned flags); H5_DLL herr_t H5AC_set_write_done_callback(H5C_t * cache_ptr, void (* write_done)(void)); diff --git a/src/H5Adense.c b/src/H5Adense.c index 4f9dcce..76ab95d 100644 --- a/src/H5Adense.c +++ b/src/H5Adense.c @@ -327,6 +327,7 @@ H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *na H5HF_t *fheap = NULL; /* Fractal heap handle */ H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */ htri_t attr_sharable; /* Flag indicating attributes are sharable */ + htri_t attr_exists; /* Attribute exists in v2 B-tree */ H5A_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(H5A_dense_open, NULL) @@ -375,7 +376,9 @@ H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *na udata.found_op_data = &ret_value; /* Find & copy the attribute in the 'name' index */ - if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0) + if((attr_exists = H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't search for attribute in name index") + else if(attr_exists == FALSE) HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't locate attribute in name index") done: @@ -841,6 +844,7 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char * H5A_t *attr_copy = NULL; /* Copy of attribute to rename */ htri_t attr_sharable; /* Flag indicating attributes are sharable */ htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */ + htri_t attr_exists; /* Attribute exists in v2 B-tree */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5A_dense_rename, FAIL) @@ -890,8 +894,10 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char * udata.found_op_data = &attr_copy; /* Get copy of attribute through 'name' tracking v2 B-tree */ - if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to find record in v2 B-tree") + if((attr_exists = H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index") + else if(attr_exists == FALSE) + HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute in name index") HDassert(attr_copy); /* Check if message is already shared */ @@ -1656,12 +1662,8 @@ H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char * udata.found_op_data = NULL; /* Find the attribute in the 'name' index */ - if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0) { - /* Assume that the failure was just not finding the attribute & clear stack */ - H5E_clear_stack(NULL); - - ret_value = FALSE; - } /* end if */ + if((ret_value = H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index") done: /* Release resources */ @@ -294,9 +294,9 @@ done: * pointers since it assumes that all nodes can be reached * from the parent node. * - * Return: Non-negative on success (if found, values returned through the - * UDATA argument). Negative on failure (if not found, UDATA is - * undefined). + * Return: Non-negative (TRUE/FALSE) on success (if found, values returned + * through the UDATA argument). Negative on failure (if not found, + * UDATA is undefined). * * Programmer: Robb Matzke * matzke@llnl.gov @@ -307,90 +307,65 @@ done: * The ADDR argument is passed by value. *------------------------------------------------------------------------- */ -herr_t +htri_t H5B_find(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr, void *udata) { H5B_t *bt = NULL; - H5B_shared_t *shared; /* Pointer to shared B-tree info */ - unsigned idx=0, lt = 0, rt; /* Final, left & right key indices */ + H5B_shared_t *shared; /* Pointer to shared B-tree info */ + unsigned idx = 0, lt = 0, rt; /* Final, left & right key indices */ int cmp = 1; /* Key comparison value */ - int ret_value = SUCCEED; /* Return value */ + htri_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5B_find, FAIL) /* * Check arguments. */ - assert(f); - assert(type); - assert(type->decode); - assert(type->cmp3); - assert(type->found); - assert(H5F_addr_defined(addr)); + HDassert(f); + HDassert(type); + HDassert(type->decode); + HDassert(type->cmp3); + HDassert(type->found); + HDassert(H5F_addr_defined(addr)); /* * Perform a binary search to locate the child which contains * the thing for which we're searching. */ - if (NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ))) + if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ))) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node") - shared=(H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared); + shared = (H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared); HDassert(shared); - rt = bt->nchildren; - while (lt < rt && cmp) { + rt = bt->nchildren; + while(lt < rt && cmp) { idx = (lt + rt) / 2; /* compare */ - if ((cmp = (type->cmp3) (f, dxpl_id, H5B_NKEY(bt,shared,idx), udata, - H5B_NKEY(bt,shared,idx+1))) < 0) { + if((cmp = (type->cmp3)(f, dxpl_id, H5B_NKEY(bt, shared, idx), udata, H5B_NKEY(bt, shared, (idx + 1)))) < 0) rt = idx; - } else { - lt = idx+1; - } - } - if (cmp) - /* 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 an object exists in the B-tree or not. -QAK - */ -#ifdef OLD_WAY - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree key not found") -#else /* OLD_WAY */ - HGOTO_DONE(FAIL) -#endif /* OLD_WAY */ + else + lt = idx + 1; + } /* end while */ + /* Check if not found */ + if(cmp) + HGOTO_DONE(FALSE) /* * Follow the link to the subtree or to the data node. */ assert(idx < bt->nchildren); - if (bt->level > 0) { - if (H5B_find(f, dxpl_id, type, bt->child[idx], 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 an object exists in the B-tree or not. -QAK - */ -#ifdef OLD_WAY - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "key not found in subtree") -#else /* OLD_WAY */ - HGOTO_DONE(FAIL) -#endif /* OLD_WAY */ - } else { - if ((type->found) (f, dxpl_id, bt->child[idx], H5B_NKEY(bt,shared,idx), 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 an object exists in the B-tree or not. -QAK - */ -#ifdef OLD_WAY - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "key not found in leaf node") -#else /* OLD_WAY */ - HGOTO_DONE(FAIL) -#endif /* OLD_WAY */ - } + if(bt->level > 0) { + if((ret_value = H5B_find(f, dxpl_id, type, bt->child[idx], udata)) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key in subtree") + } /* end if */ + else { + if((ret_value = (type->found)(f, dxpl_id, bt->child[idx], H5B_NKEY(bt, shared, idx), udata)) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key in leaf node") + } /* end else */ done: - if (bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) - < 0) + if(bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release node") FUNC_LEAVE_NOAPI(ret_value) @@ -1533,16 +1508,14 @@ H5B_remove_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type bt->left = HADDR_UNDEF; bt->right = HADDR_UNDEF; H5_CHECK_OVERFLOW(shared->sizeof_rnode,size_t,hsize_t); - if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)shared->sizeof_rnode)<0 - || H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, bt_flags | H5C__DELETED_FLAG)<0) { + if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, bt_flags | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) { bt = NULL; bt_flags = H5AC__NO_FLAGS_SET; HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, H5B_INS_ERROR, "unable to free B-tree node") - } + } /* end if */ bt = NULL; bt_flags = H5AC__NO_FLAGS_SET; - } - + } /* end if */ } else if (H5B_INS_REMOVE==ret_value && 0==idx) { /* * The subtree is the left-most child of this node. We discard the @@ -1766,12 +1739,8 @@ H5B_delete(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr, void } /* end if */ } /* end else */ - /* Delete this node from disk */ - if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)shared->sizeof_rnode)<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node") - done: - if (bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5C__DELETED_FLAG)<0) + if(bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG)<0) HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node in cache") FUNC_LEAVE_NOAPI(ret_value) @@ -314,10 +314,10 @@ done: * OP_DATA pointer, to allow caller to return information about * the record. * - * If 'OP' is NULL, then this routine just returns "SUCCEED" when + * If 'OP' is NULL, then this routine just returns "TRUE" when * a record is present in the B-tree. * - * Return: Non-negative on success, negative on failure. + * Return: Non-negative (TRUE/FALSE) on success, negative on failure. * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu @@ -325,7 +325,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +htri_t H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, void *udata, H5B2_found_t op, void *op_data) { @@ -337,7 +337,7 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, unsigned depth; /* Current depth of the tree */ int cmp; /* Comparison value of records */ unsigned idx; /* Location of record which matches key */ - herr_t ret_value = SUCCEED; + htri_t ret_value = TRUE /* Return value */; FUNC_ENTER_NOAPI(H5B2_find, FAIL) @@ -372,7 +372,7 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, /* Check for empty tree */ if(curr_node_ptr.node_nrec == 0) - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree has no records") + HGOTO_DONE(FALSE) /* Walk down B-tree to find record or leaf node where record is located */ cmp = -1; @@ -404,7 +404,7 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, /* Make callback for current record */ if(op && (op)(H5B2_INT_NREC(internal, shared, idx), op_data) < 0) { /* Unlock current node */ - if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0) + if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation") @@ -414,7 +414,8 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") - HGOTO_DONE(SUCCEED); + /* Indicate record found */ + HGOTO_DONE(TRUE) } /* end else */ /* Decrement depth we're at in B-tree */ @@ -436,15 +437,8 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") - /* 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 an object exists in the B-tree or not. -QAK - */ -#ifdef OLD_WAY - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "key not found in leaf node") -#else /* OLD_WAY */ - HGOTO_DONE(FAIL) -#endif /* OLD_WAY */ + /* Record not found */ + HGOTO_DONE(FALSE) } /* end if */ else { /* Make callback for current record */ @@ -992,13 +986,9 @@ H5B2_delete(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, if(H5B2_delete_node(f, dxpl_id, bt2->shared, shared->depth, &bt2->root, op, op_data) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to delete B-tree nodes") - /* Release space for B-tree node on disk */ - if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5B2_HEADER_SIZE(f))<0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree header info") - done: /* Release the B-tree header info */ - if(bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__DELETED_FLAG) < 0) + if(bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to delete B-tree header info") FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5B2cache.c b/src/H5B2cache.c index 1d34eb0..5882ce9 100644 --- a/src/H5B2cache.c +++ b/src/H5B2cache.c @@ -30,12 +30,14 @@ #define H5B2_PACKAGE /*suppress error about including H5B2pkg */ + /***********/ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ #include "H5B2pkg.h" /* v2 B-trees */ #include "H5Eprivate.h" /* Error handling */ +#include "H5MFprivate.h" /* File memory management */ #include "H5WBprivate.h" /* Wrapped Buffers */ @@ -80,6 +82,7 @@ static herr_t H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, ha static herr_t H5B2_cache_leaf_clear(H5F_t *f, H5B2_leaf_t *l, hbool_t destroy); static herr_t H5B2_cache_leaf_size(const H5F_t *f, const H5B2_leaf_t *l, size_t *size_ptr); + /*********************/ /* Package Variables */ /*********************/ @@ -114,6 +117,7 @@ const H5AC_class_t H5AC_BT2_LEAF[1] = {{ (H5AC_size_func_t)H5B2_cache_leaf_size, }}; + /*****************************/ /* Library Private Variables */ /*****************************/ @@ -376,17 +380,29 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ herr_t -H5B2_cache_hdr_dest(H5F_t UNUSED *f, H5B2_t *bt2) +H5B2_cache_hdr_dest(H5F_t *f, H5B2_t *bt2) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_hdr_dest) + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_hdr_dest) /* * Check arguments. */ HDassert(bt2); + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!bt2->cache_info.free_file_space_on_destroy || H5F_addr_defined(bt2->cache_info.addr)); + + /* Check for freeing file space for B-tree header */ + if(bt2->cache_info.free_file_space_on_destroy) { + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, bt2->cache_info.addr, (hsize_t)H5B2_HEADER_SIZE(f)) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree header") + } /* end if */ + /* Decrement reference count on shared B-tree info */ if(bt2->shared) H5RC_DEC(bt2->shared); @@ -394,7 +410,8 @@ H5B2_cache_hdr_dest(H5F_t UNUSED *f, H5B2_t *bt2) /* Free B-tree header info */ (void)H5FL_FREE(H5B2_t, bt2); - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5B2_cache_hdr_dest() */ @@ -712,23 +729,34 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ herr_t -H5B2_cache_internal_dest(H5F_t UNUSED *f, H5B2_internal_t *internal) +H5B2_cache_internal_dest(H5F_t *f, H5B2_internal_t *internal) { H5B2_shared_t *shared; /* Shared B-tree information */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_internal_dest) + FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_internal_dest) /* * Check arguments. */ HDassert(internal); + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!internal->cache_info.free_file_space_on_destroy || H5F_addr_defined(internal->cache_info.addr)); + /* Get the pointer to the shared B-tree info */ shared = (H5B2_shared_t *)H5RC_GET_OBJ(internal->shared); HDassert(shared); + /* Check for freeing file space for B-tree internal node */ + if(internal->cache_info.free_file_space_on_destroy) { + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, internal->cache_info.addr, (hsize_t)shared->node_size) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree internal node") + } /* end if */ + /* Release internal node's native key buffer */ if(internal->int_native) H5FL_FAC_FREE(shared->node_info[internal->depth].nat_rec_fac, internal->int_native); @@ -744,7 +772,8 @@ H5B2_cache_internal_dest(H5F_t UNUSED *f, H5B2_internal_t *internal) /* Free B-tree internal node info */ (void)H5FL_FREE(H5B2_internal_t, internal); - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5B2_cache_internal_dest() */ @@ -1035,23 +1064,34 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ herr_t -H5B2_cache_leaf_dest(H5F_t UNUSED *f, H5B2_leaf_t *leaf) +H5B2_cache_leaf_dest(H5F_t *f, H5B2_leaf_t *leaf) { H5B2_shared_t *shared; /* Shared B-tree information */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_leaf_dest) + FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_leaf_dest) /* * Check arguments. */ HDassert(leaf); + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!leaf->cache_info.free_file_space_on_destroy || H5F_addr_defined(leaf->cache_info.addr)); + /* Get the pointer to the shared B-tree info */ shared = (H5B2_shared_t *)H5RC_GET_OBJ(leaf->shared); HDassert(shared); + /* Check for freeing file space for B-tree leaf node */ + if(leaf->cache_info.free_file_space_on_destroy) { + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, leaf->cache_info.addr, (hsize_t)shared->node_size) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree leaf node") + } /* end if */ + /* Release leaf's native key buffer */ if(leaf->leaf_native) H5FL_FAC_FREE(shared->node_info[0].nat_rec_fac, leaf->leaf_native); @@ -1063,7 +1103,8 @@ H5B2_cache_leaf_dest(H5F_t UNUSED *f, H5B2_leaf_t *leaf) /* Free B-tree leaf node info */ (void)H5FL_FREE(H5B2_leaf_t, leaf); - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5B2_cache_leaf_dest() */ diff --git a/src/H5B2int.c b/src/H5B2int.c index d70b412..82185c0 100644 --- a/src/H5B2int.c +++ b/src/H5B2int.c @@ -1350,9 +1350,7 @@ H5B2_merge2(H5F_t *f, hid_t dxpl_id, unsigned depth, HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") /* Delete right node & remove from cache (marked as dirty) */ - if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") - if(H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0) + if(H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") done: @@ -1574,9 +1572,7 @@ H5B2_merge3(H5F_t *f, hid_t dxpl_id, unsigned depth, HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") /* Delete right node & remove from cache (marked as dirty) */ - if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") - if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0) + if(H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node") done: @@ -2280,12 +2276,8 @@ H5B2_remove_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, HDmemmove(H5B2_LEAF_NREC(leaf, shared, idx), H5B2_LEAF_NREC(leaf, shared, (idx + 1)), shared->type->nrec_size * (leaf->nrec-idx)); } /* end if */ else { - /* Release space for B-tree node on disk */ - if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, leaf_addr, (hsize_t)shared->node_size) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") - /* Let the cache know that the object is deleted */ - leaf_flags |= H5AC__DELETED_FLAG; + leaf_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; /* Reset address of parent node pointer */ curr_node_ptr->addr = HADDR_UNDEF; @@ -2367,12 +2359,8 @@ H5B2_remove_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, parent_cache_info_flags_ptr, internal, &internal_flags, 0) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node") - /* Release space for root B-tree node on disk */ - if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, internal_addr, (hsize_t)shared->node_size) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") - /* Let the cache know that the object is deleted */ - internal_flags |= H5AC__DELETED_FLAG; + internal_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; /* Reset information in header's root node pointer */ curr_node_ptr->addr = internal->node_ptrs[0].addr; @@ -2580,12 +2568,8 @@ H5B2_remove_leaf_by_idx(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, HDmemmove(H5B2_LEAF_NREC(leaf, shared, idx), H5B2_LEAF_NREC(leaf, shared, (idx + 1)), shared->type->nrec_size * (leaf->nrec-idx)); } /* end if */ else { - /* Release space for B-tree node on disk */ - if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, leaf_addr, (hsize_t)shared->node_size) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") - /* Let the cache know that the object is deleted */ - leaf_flags |= H5AC__DELETED_FLAG; + leaf_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; /* Reset address of parent node pointer */ curr_node_ptr->addr = HADDR_UNDEF; @@ -2671,12 +2655,8 @@ H5B2_remove_internal_by_idx(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, parent_cache_info_flags_ptr, internal, &internal_flags, 0) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node") - /* Release space for root B-tree node on disk */ - if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, internal_addr, (hsize_t)shared->node_size) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node") - /* Let the cache know that the object is deleted */ - internal_flags |= H5AC__DELETED_FLAG; + internal_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; /* Reset information in header's root node pointer */ curr_node_ptr->addr = internal->node_ptrs[0].addr; @@ -3134,15 +3114,10 @@ H5B2_delete_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth, } /* end for */ } /* end if */ - /* Release space for current B-tree node on disk */ - if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, curr_node->addr, (hsize_t)shared->node_size) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node") - done: /* Unlock & delete current node */ - if(node) - if(H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG) < 0) - HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") + if(node && H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) + HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node") FUNC_LEAVE_NOAPI(ret_value) } /* H5B2_delete_node() */ diff --git a/src/H5B2private.h b/src/H5B2private.h index 6d8172c..0a18604 100644 --- a/src/H5B2private.h +++ b/src/H5B2private.h @@ -124,7 +124,7 @@ H5_DLL herr_t H5B2_iterate(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, H5B2_operator_t op, void *op_data); H5_DLL herr_t H5B2_iterate_size(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, hsize_t *op_data); -H5_DLL herr_t H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, +H5_DLL htri_t H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, void *udata, H5B2_found_t op, void *op_data); H5_DLL herr_t H5B2_index(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, H5_iter_order_t order, hsize_t idx, H5B2_found_t op, diff --git a/src/H5Bcache.c b/src/H5Bcache.c index d3b2a35..9765552 100644 --- a/src/H5Bcache.c +++ b/src/H5Bcache.c @@ -37,6 +37,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Bpkg.h" /* B-link trees */ #include "H5Eprivate.h" /* Error handling */ +#include "H5MFprivate.h" /* File memory management */ /****************/ /* Local Macros */ @@ -321,24 +322,45 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ herr_t -H5B_dest(H5F_t UNUSED *f, H5B_t *bt) +H5B_dest(H5F_t *f, H5B_t *bt) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B_dest) + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B_dest) /* * Check arguments. */ + HDassert(f); HDassert(bt); HDassert(bt->rc_shared); + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!bt->cache_info.free_file_space_on_destroy || H5F_addr_defined(bt->cache_info.addr)); + + /* Check for freeing file space for B-tree node */ + if(bt->cache_info.free_file_space_on_destroy) { + H5B_shared_t *shared; /* Pointer to shared B-tree info */ + + /* Get the pointer to the shared B-tree info */ + shared = (H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared); + HDassert(shared); + + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, bt->cache_info.addr, (hsize_t)shared->sizeof_rnode) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node") + } /* end if */ + + /* Release resources for B-tree node */ H5FL_SEQ_FREE(haddr_t, bt->child); (void)H5FL_BLK_FREE(native_block, bt->native); H5RC_DEC(bt->rc_shared); (void)H5FL_FREE(H5B_t, bt); - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5B_dest() */ diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h index dc8648e..c11d02c 100644 --- a/src/H5Bprivate.h +++ b/src/H5Bprivate.h @@ -103,7 +103,7 @@ typedef struct H5B_class_t { herr_t (*new_node)(H5F_t*, hid_t, H5B_ins_t, void*, void*, void*, haddr_t*); int (*cmp2)(H5F_t*, hid_t, void*, void*, void*); /*compare 2 keys */ int (*cmp3)(H5F_t*, hid_t, void*, void*, void*); /*compare 3 keys */ - herr_t (*found)(H5F_t*, hid_t, haddr_t, const void*, void*); + htri_t (*found)(H5F_t*, hid_t, haddr_t, const void*, void*); /* insert new data */ H5B_ins_t (*insert)(H5F_t*, hid_t, haddr_t, void*, hbool_t*, void*, void*, @@ -3412,15 +3412,19 @@ H5C_expunge_entry(H5F_t * f, hid_t secondary_dxpl_id, H5C_t * cache_ptr, const H5C_class_t * type, - haddr_t addr) + haddr_t addr, + unsigned flags) { herr_t result; - herr_t ret_value = SUCCEED; /* Return value */ hbool_t first_flush = TRUE; + hbool_t free_file_space; H5C_cache_entry_t * entry_ptr = NULL; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5C_expunge_entry, FAIL) + free_file_space = ( (flags & H5C__FREE_FILE_SPACE_FLAG) != 0 ); + HDassert( H5F_addr_defined(addr) ); HDassert( cache_ptr ); HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); @@ -3459,6 +3463,11 @@ H5C_expunge_entry(H5F_t * f, "Target entry is pinned.") } + /* Pass along 'free file space' flag to cache client */ + + entry_ptr->free_file_space_on_destroy = free_file_space; + + /* If we get this far, call H5C_flush_single_entry() with the * H5C__FLUSH_INVALIDATE_FLAG and the H5C__FLUSH_CLEAR_ONLY_FLAG. * This will clear the entry, and then delete it from the cache. @@ -4611,6 +4620,10 @@ done: * JRM -- 12/31/07 * Added code supporting flash cache size increases. * + * QAK -- 1/31/08 + * Added initialization for the new free_file_space_on_destroy + * field. + * *------------------------------------------------------------------------- */ @@ -4692,6 +4705,7 @@ H5C_insert_entry(H5F_t * f, entry_ptr->flush_in_progress = FALSE; entry_ptr->destroy_in_progress = FALSE; + entry_ptr->free_file_space_on_destroy = FALSE; entry_ptr->ht_next = NULL; entry_ptr->ht_prev = NULL; @@ -7413,7 +7427,15 @@ done: * ro_ref_count parameters. * * JRM -- 12/31/07 - * Modified funtion to support flash cache resizes. + * Modified function to support flash cache resizes. + * + * QAK -- 1/31/08 + * Modified function to support freeing file space in client's + * 'dest' callback routine. + * + * QAK -- 2/07/08 + * Separated "destroy entry" concept from "remove entry from + * cache" concept, by adding the 'take_ownership' flag. * *------------------------------------------------------------------------- */ @@ -7435,6 +7457,8 @@ H5C_unprotect(H5F_t * f, hbool_t size_changed; hbool_t pin_entry; hbool_t unpin_entry; + hbool_t free_file_space; + hbool_t take_ownership; #ifdef H5_HAVE_PARALLEL hbool_t clear_entry = FALSE; #endif /* H5_HAVE_PARALLEL */ @@ -7452,6 +7476,8 @@ H5C_unprotect(H5F_t * f, size_changed = ( (flags & H5C__SIZE_CHANGED_FLAG) != 0 ); pin_entry = ( (flags & H5C__PIN_ENTRY_FLAG) != 0 ); unpin_entry = ( (flags & H5C__UNPIN_ENTRY_FLAG) != 0 ); + free_file_space = ( (flags & H5C__FREE_FILE_SPACE_FLAG) != 0 ); + take_ownership = ( (flags & H5C__TAKE_OWNERSHIP_FLAG) != 0 ); /* Changing the size of an entry dirties it. Thus, set the * dirtied flag if the size_changed flag is set. @@ -7471,6 +7497,9 @@ H5C_unprotect(H5F_t * f, HDassert( ( ! size_changed ) || ( dirtied ) ); HDassert( ( ! size_changed ) || ( new_size > 0 ) ); HDassert( ! ( pin_entry && unpin_entry ) ); + HDassert( ( ! free_file_space ) || ( deleted ) ); /* deleted flag must accompany free_file_space */ + HDassert( ( ! take_ownership ) || ( deleted ) ); /* deleted flag must accompany take_ownership */ + HDassert( ! ( free_file_space && take_ownership ) ); /* can't have both free_file_space & take_ownership */ entry_ptr = (H5C_cache_entry_t *)thing; @@ -7696,7 +7725,9 @@ H5C_unprotect(H5F_t * f, * H5C__FLUSH_CLEAR_ONLY_FLAG and H5C__FLUSH_INVALIDATE_FLAG flags. * However, it is needed for the function call. */ - hbool_t dummy_first_flush = TRUE; + hbool_t dummy_first_flush = TRUE; + unsigned flush_flags = (H5C__FLUSH_CLEAR_ONLY_FLAG | + H5C__FLUSH_INVALIDATE_FLAG); /* we can't delete a pinned entry */ HDassert ( ! (entry_ptr->is_pinned ) ); @@ -7716,14 +7747,23 @@ H5C_unprotect(H5F_t * f, "hash table contains multiple entries for addr?!?.") } + /* Pass along 'free file space' flag to cache client */ + + entry_ptr->free_file_space_on_destroy = free_file_space; + + /* Set the "take ownership" flag for the flush, if needed */ + if ( take_ownership) { + + flush_flags |= H5C__TAKE_OWNERSHIP_FLAG; + } + if ( H5C_flush_single_entry(f, primary_dxpl_id, secondary_dxpl_id, cache_ptr, type, addr, - (H5C__FLUSH_CLEAR_ONLY_FLAG | - H5C__FLUSH_INVALIDATE_FLAG), + flush_flags, &dummy_first_flush, TRUE) < 0 ) { @@ -10004,11 +10044,15 @@ done: * in which the target entry is resized during flush, and * update the caches data structures accordingly. * - * * JRM -- 3/29/07 * Added sanity checks on the new is_read_only and * ro_ref_count fields. * + * QAK -- 2/07/08 + * Separated "destroy entry" concept from "remove entry from + * cache" concept, by adding the 'take_ownership' flag and + * the "destroy_entry" variable. + * *------------------------------------------------------------------------- */ static herr_t @@ -10024,12 +10068,14 @@ H5C_flush_single_entry(H5F_t * f, { hbool_t destroy; hbool_t clear_only; + hbool_t take_ownership; hbool_t was_dirty; - herr_t ret_value = SUCCEED; /* Return value */ + hbool_t destroy_entry; herr_t status; int type_id; unsigned flush_flags = H5C_CALLBACK__NO_FLAGS_SET; H5C_cache_entry_t * entry_ptr = NULL; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5C_flush_single_entry) @@ -10042,6 +10088,15 @@ H5C_flush_single_entry(H5F_t * f, destroy = ( (flags & H5C__FLUSH_INVALIDATE_FLAG) != 0 ); clear_only = ( (flags & H5C__FLUSH_CLEAR_ONLY_FLAG) != 0); + take_ownership = ( (flags & H5C__TAKE_OWNERSHIP_FLAG) != 0); + + /* Set the flag for destroying the entry, based on the 'take ownership' + * and 'destroy' flags + */ + if(take_ownership) + destroy_entry = FALSE; + else + destroy_entry = destroy; /* attempt to find the target entry in the hash table */ H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL) @@ -10308,7 +10363,7 @@ H5C_flush_single_entry(H5F_t * f, } #endif /* NDEBUG */ /* Call the callback routine to clear all dirty flags for object */ - if ( (entry_ptr->type->clear)(f, entry_ptr, destroy) < 0 ) { + if ( (entry_ptr->type->clear)(f, entry_ptr, destroy_entry) < 0 ) { HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't clear entry") } @@ -10341,7 +10396,7 @@ H5C_flush_single_entry(H5F_t * f, if ( *first_flush_ptr && entry_ptr->is_dirty ) { - status = (entry_ptr->type->flush)(f, primary_dxpl_id, destroy, + status = (entry_ptr->type->flush)(f, primary_dxpl_id, destroy_entry, entry_ptr->addr, entry_ptr, &flush_flags); *first_flush_ptr = FALSE; @@ -10349,7 +10404,7 @@ H5C_flush_single_entry(H5F_t * f, } else { status = (entry_ptr->type->flush)(f, secondary_dxpl_id, - destroy, entry_ptr->addr, + destroy_entry, entry_ptr->addr, entry_ptr, &flush_flags); } @@ -10534,6 +10589,10 @@ done: * Added initialization for the new is_read_only and * ro_ref_count fields. * + * QAK -- 1/31/08 + * Added initialization for the new free_file_space_on_destroy + * field. + * *------------------------------------------------------------------------- */ @@ -10609,6 +10668,7 @@ H5C_load_entry(H5F_t * f, #endif /* H5_HAVE_PARALLEL */ entry_ptr->flush_in_progress = FALSE; entry_ptr->destroy_in_progress = FALSE; + entry_ptr->free_file_space_on_destroy = FALSE; if ( (type->size)(f, thing, &(entry_ptr->size)) < 0 ) { diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index b50227b..4ce321c 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -364,6 +364,11 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr, * destroy_in_progress: Boolean flag that is set to true iff the entry * is in the process of being flushed and destroyed. * + * free_file_space_on_destroy: Boolean flag that is set to true iff the entry + * is in the process of being flushed and destroyed and the file + * space used by the object should be freed by the cache client's + * 'dest' callback routine. + * * * Fields supporting the hash table: * @@ -489,6 +494,7 @@ typedef struct H5C_cache_entry_t #endif /* H5_HAVE_PARALLEL */ hbool_t flush_in_progress; hbool_t destroy_in_progress; + hbool_t free_file_space_on_destroy; /* fields supporting the hash table: */ @@ -893,7 +899,12 @@ typedef struct H5C_auto_size_ctl_t * H5C__SIZE_CHANGED_FLAG * H5C__PIN_ENTRY_FLAG * H5C__UNPIN_ENTRY_FLAG + * H5C__FREE_FILE_SPACE_FLAG + * H5C__TAKE_OWNERSHIP_FLAG + * + * These flags apply to H5C_expunge_entry(): * + * H5C__FREE_FILE_SPACE_FLAG * * These flags apply to H5C_flush_cache(): * @@ -908,6 +919,7 @@ typedef struct H5C_auto_size_ctl_t * H5C__FLUSH_INVALIDATE_FLAG * H5C__FLUSH_CLEAR_ONLY_FLAG * H5C__FLUSH_MARKED_ENTRIES_FLAG + * H5C__TAKE_OWNERSHIP_FLAG */ #define H5C__NO_FLAGS_SET 0x0000 @@ -922,6 +934,8 @@ typedef struct H5C_auto_size_ctl_t #define H5C__FLUSH_MARKED_ENTRIES_FLAG 0x0100 #define H5C__FLUSH_IGNORE_PROTECTED_FLAG 0x0200 #define H5C__READ_ONLY_FLAG 0x0400 +#define H5C__FREE_FILE_SPACE_FLAG 0x0800 +#define H5C__TAKE_OWNERSHIP_FLAG 0x1000 H5_DLL H5C_t * H5C_create(size_t max_cache_size, @@ -954,7 +968,8 @@ H5_DLL herr_t H5C_expunge_entry(H5F_t * f, hid_t secondary_dxpl_id, H5C_t * cache_ptr, const H5C_class_t * type, - haddr_t addr); + haddr_t addr, + unsigned flags); H5_DLL herr_t H5C_flush_cache(H5F_t * f, hid_t primary_dxpl_id, diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index 0692774..202da75 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -1484,17 +1484,17 @@ H5D_chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_info_t *chunk_info; /* Chunk information */ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */ void *chunk; /* Pointer to locked chunk buffer */ - haddr_t chunk_addr; /* Chunk address on disk */ H5D_chunk_ud_t udata; /* B-tree pass-through */ /* Get the actual chunk information from the skip list node */ chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node); - /* Get the address of the chunk in the file */ - chunk_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata); + /* Get the info for the chunk in the file */ + if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") /* Check for non-existant chunk & skip it if appropriate */ - if(!H5F_addr_defined(chunk_addr) && !H5D_chunk_in_cache(io_info->dset, chunk_info->coords, chunk_info->index) + if(!H5F_addr_defined(udata.addr) && !H5D_chunk_in_cache(io_info->dset, chunk_info->coords, chunk_info->index) && skip_missing_chunks) { /* No chunk cached */ chunk = NULL; @@ -1504,7 +1504,7 @@ H5D_chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, } /* end if */ else { /* Load the chunk into cache and lock it. */ - if(H5D_chunk_cacheable(io_info, chunk_addr)) { + if(H5D_chunk_cacheable(io_info, udata.addr)) { /* Pass in chunk's coordinates in a union. */ io_info->store->chunk.offset = chunk_info->coords; io_info->store->chunk.index = chunk_info->index; @@ -1524,10 +1524,10 @@ H5D_chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, } /* end if */ else { /* Sanity check */ - HDassert(H5F_addr_defined(chunk_addr)); + HDassert(H5F_addr_defined(udata.addr)); /* Set up the storage address information for this chunk */ - ctg_store.contig.dset_addr = chunk_addr; + ctg_store.contig.dset_addr = udata.addr; /* No chunk cached */ chunk = NULL; @@ -1612,7 +1612,6 @@ H5D_chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_info_t *chunk_info; /* Chunk information */ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */ void *chunk; /* Pointer to locked chunk buffer */ - haddr_t chunk_addr; /* Chunk address on disk */ H5D_chunk_ud_t udata; /* B-tree pass-through */ /* Get the actual chunk information from the skip list node */ @@ -1620,8 +1619,9 @@ H5D_chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, /* Load the chunk into cache. But if the whole chunk is written, * simply allocate space instead of load the chunk. */ - chunk_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata); - if(H5D_chunk_cacheable(io_info, chunk_addr)) { + if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address") + if(H5D_chunk_cacheable(io_info, udata.addr)) { hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */ /* Pass in chunk's coordinates in a union. */ @@ -1648,10 +1648,10 @@ H5D_chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, } /* end if */ else { /* Sanity check */ - HDassert(H5F_addr_defined(chunk_addr)); + HDassert(H5F_addr_defined(udata.addr)); /* Set up the storage address information for this chunk */ - ctg_store.contig.dset_addr = chunk_addr; + ctg_store.contig.dset_addr = udata.addr; /* No chunk cached */ chunk = NULL; @@ -1945,9 +1945,9 @@ done: /*------------------------------------------------------------------------- - * Function: H5D_chunk_get_addr + * Function: H5D_chunk_get_info * - * Purpose: Get the file address of a chunk if file space has been + * Purpose: Get the info about a chunk if file space has been * assigned. Save the retrieved information in the udata * supplied. * @@ -1958,26 +1958,24 @@ done: * *------------------------------------------------------------------------- */ -haddr_t -H5D_chunk_get_addr(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset, - H5D_chunk_ud_t *_udata) +herr_t +H5D_chunk_get_info(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset, + H5D_chunk_ud_t *udata) { - H5D_chunk_ud_t tmp_udata; /* Information about a chunk */ - H5D_chunk_ud_t *udata; /* Pointer to information about a chunk */ - haddr_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_get_addr) + FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_get_info) HDassert(dset); HDassert(dset->shared->layout.u.chunk.ndims > 0); HDassert(chunk_offset); + HDassert(udata); - /* Check for udata struct to return */ - udata = (_udata != NULL ? _udata : &tmp_udata); - - /* Initialize the information about the chunk we are looking for */ + /* Initialize the query information about the chunk we are looking for */ udata->common.mesg = &(dset->shared->layout); udata->common.offset = chunk_offset; + + /* Reset information about the chunk we are looking for */ udata->nbytes = 0; udata->filter_mask = 0; udata->addr = HADDR_UNDEF; @@ -1992,24 +1990,16 @@ H5D_chunk_get_addr(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset idx_info.layout = &dset->shared->layout; /* Go get the chunk information */ - if(!H5F_addr_defined((dset->shared->layout.u.chunk.ops->get_addr)(&idx_info, udata))) { - /* Cache the fact that the chunk is not in the B-tree */ - H5D_chunk_cinfo_cache_update(&dset->shared->cache.chunk.last, udata); - - HGOTO_DONE(HADDR_UNDEF) - } /* end if */ + if((dset->shared->layout.u.chunk.ops->get_addr)(&idx_info, udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query chunk address") /* Cache the information retrieved */ - HDassert(H5F_addr_defined(udata->addr)); H5D_chunk_cinfo_cache_update(&dset->shared->cache.chunk.last, udata); } /* end if */ - /* Success! Set the return value */ - ret_value = udata->addr; - done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5D_chunk_get_addr() */ +} /* H5D_chunk_get_info() */ /*------------------------------------------------------------------------- @@ -2381,9 +2371,10 @@ H5D_chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_lock) HDassert(io_info); - HDassert(dset); HDassert(io_info->dxpl_cache); HDassert(io_info->store); + HDassert(udata); + HDassert(dset); HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER)); /* Get the chunk's size */ @@ -2426,20 +2417,13 @@ H5D_chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, HDmemset(chunk, 0, chunk_size); } /* end if */ else { - H5D_chunk_ud_t tmp_udata; /*B-tree pass-through */ - - if(udata != NULL) - chunk_addr = udata->addr; - else { - /* Point at temporary storage for B-tree pass through */ - udata = &tmp_udata; + /* + * Not in the cache. Count this as a miss if it's in the file + * or an init if it isn't. + */ - /* - * Not in the cache. Read it from the file and count this as a miss - * if it's in the file or an init if it isn't. - */ - chunk_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, io_info->store->chunk.offset, udata); - } /* end else */ + /* Save the chunk address */ + chunk_addr = udata->addr; /* Check if the chunk exists on disk */ if(H5F_addr_defined(chunk_addr)) { @@ -2972,14 +2956,15 @@ H5D_chunk_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) /* Loop over all chunks */ carry = FALSE; while(!carry) { - haddr_t chunk_addr; /* Address of chunk */ + H5D_chunk_ud_t udata; /* User data for querying chunk info */ int i; /* Local index variable */ - /* Get the chunk's address */ - chunk_addr = H5D_chunk_get_addr(dset, dxpl_id, chunk_offset, NULL); + /* Get the chunk's info */ + if(H5D_chunk_get_info(dset, dxpl_id, chunk_offset, &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "error looking up chunk address") /* Check if the chunk exists yet on disk */ - if(!H5F_addr_defined(chunk_addr)) { + if(!H5F_addr_defined(udata.addr)) { const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /* Raw data chunk cache */ H5D_rdcc_ent_t *ent; /* Cache entry */ hbool_t chunk_exists; /* Flag to indicate whether a chunk exists already */ diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index 88ffdc6..01ee5e2 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -608,7 +608,6 @@ for(u = 0; u < mem_max_nseq; u++) haddr_t sieve_start = HADDR_UNDEF, sieve_end = HADDR_UNDEF; /* Start & end locations of sieve buffer */ haddr_t contig_end; /* End locations of block to write */ size_t sieve_size = (size_t)-1; /* size of sieve buffer */ - haddr_t abs_eoa; /* Absolute end of file address */ haddr_t rel_eoa; /* Relative end of file address */ hsize_t max_data; /* Actual maximum size of data to cache */ @@ -653,12 +652,9 @@ for(u = 0; u < mem_max_nseq; u++) dset_contig->sieve_loc=addr; /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file))) + if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size") - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa = abs_eoa - H5F_get_base_addr(file); - /* Set up the buffer parameters */ max_data = store_contig->dset_size-dset_offset_arr[u]; @@ -730,12 +726,9 @@ for(u = 0; u < mem_max_nseq; u++) dset_contig->sieve_loc=addr; /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file))) + if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size") - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-H5F_get_base_addr(file); - /* Only need this when resizing sieve buffer */ max_data=store_contig->dset_size-dset_offset_arr[u]; @@ -872,7 +865,6 @@ H5D_contig_writevv(const H5D_io_info_t *io_info, haddr_t sieve_start=HADDR_UNDEF, sieve_end=HADDR_UNDEF; /* Start & end locations of sieve buffer */ haddr_t contig_end; /* End locations of block to write */ size_t sieve_size=(size_t)-1; /* size of sieve buffer */ - haddr_t abs_eoa; /* Absolute end of file address */ haddr_t rel_eoa; /* Relative end of file address */ hsize_t max_data; /* Actual maximum size of data to cache */ @@ -921,12 +913,9 @@ if(dset_contig->sieve_size > size) dset_contig->sieve_loc=addr; /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file))) + if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size") - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-H5F_get_base_addr(file); - /* Set up the buffer parameters */ max_data=store_contig->dset_size-dset_offset_arr[u]; @@ -1040,12 +1029,9 @@ if(dset_contig->sieve_size > size) dset_contig->sieve_loc=addr; /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file))) + if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size") - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-H5F_get_base_addr(file); - /* Only need this when resizing sieve buffer */ max_data=store_contig->dset_size-dset_offset_arr[u]; diff --git a/src/H5Dint.c b/src/H5Dint.c index bab3038..aa91db5 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -1484,7 +1484,7 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id) * This is important only for parallel I/O where the space must * be fully allocated before I/O can happen. */ - if((H5F_get_intent(dataset->oloc.file) & H5F_ACC_RDWR) + if((H5F_INTENT(dataset->oloc.file) & H5F_ACC_RDWR) && ((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)) { @@ -1730,33 +1730,6 @@ H5D_typeof(const H5D_t *dset) /*------------------------------------------------------------------------- - * Function: H5D_get_file - * - * Purpose: Returns the dataset's file pointer. - * - * Return: Success: Ptr to the dataset's file pointer. - * - * Failure: NULL - * - * Programmer: Quincey Koziol - * Thursday, October 22, 1998 - * - *------------------------------------------------------------------------- - */ -static H5F_t * -H5D_get_file(const H5D_t *dset) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_get_file) - - HDassert(dset); - HDassert(dset->oloc.file); - - FUNC_LEAVE_NOAPI(dset->oloc.file) -} /* end H5D_get_file() */ - - -/*------------------------------------------------------------------------- * Function: H5D_alloc_storage * * Purpose: Allocate storage for the raw data of a dataset. @@ -2036,8 +2009,6 @@ done: haddr_t H5D_get_offset(const H5D_t *dset) { - haddr_t base_addr; - H5F_t *f; haddr_t ret_value = HADDR_UNDEF; FUNC_ENTER_NOAPI_NOINIT(H5D_get_offset) @@ -2052,15 +2023,9 @@ H5D_get_offset(const H5D_t *dset) case H5D_CONTIGUOUS: /* If dataspace hasn't been allocated or dataset is stored in * an external file, the value will be HADDR_UNDEF. */ - f = H5D_get_file(dset); - base_addr = H5F_get_base_addr(f); - - /* If there's user block in file, returns the absolute dataset offset - * from the beginning of file. */ - if(base_addr != HADDR_UNDEF) - ret_value = dset->shared->layout.u.contig.addr + base_addr; - else - ret_value = dset->shared->layout.u.contig.addr; + if(dset->shared->dcpl_cache.efl.nused == 0 || H5F_addr_defined(dset->shared->layout.u.contig.addr)) + /* Return the absolute dataset offset from the beginning of file. */ + ret_value = dset->shared->layout.u.contig.addr + H5F_BASE_ADDR(dset->oloc.file); break; default: @@ -2325,7 +2290,7 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id) HDassert(size); /* Check if we are allowed to modify this file */ - if(0 == (H5F_get_intent(dset->oloc.file) & H5F_ACC_RDWR)) + if(0 == (H5F_INTENT(dset->oloc.file) & H5F_ACC_RDWR)) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "no write intent on file") /* Check if the filters in the DCPL will need to encode, and if so, can they? */ diff --git a/src/H5Distore.c b/src/H5Distore.c index a217a41..5d24d63 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -139,7 +139,7 @@ static int H5D_istore_cmp2(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata, void *_rt_key); static int H5D_istore_cmp3(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata, void *_rt_key); -static herr_t H5D_istore_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key, +static htri_t H5D_istore_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key, void *_udata); static H5B_ins_t H5D_istore_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key, hbool_t *lt_key_changed, void *_md_key, @@ -162,7 +162,7 @@ static herr_t H5D_istore_idx_init(const H5D_chk_idx_info_t *idx_info); static herr_t H5D_istore_idx_create(const H5D_chk_idx_info_t *idx_info); static herr_t H5D_istore_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata); -static haddr_t H5D_istore_idx_get_addr(const H5D_chk_idx_info_t *idx_info, +static herr_t H5D_istore_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata); static int H5D_istore_idx_iterate(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb, void *chunk_udata); @@ -583,8 +583,8 @@ done: * called with the maximum stored chunk indices less than the * requested chunk indices. * - * Return: Non-negative on success with information about the chunk - * returned through the UDATA argument. Negative on failure. + * Return: Non-negative (TRUE/FALSE) on success with information about the + * chunk returned through the UDATA argument. Negative on failure. * * Programmer: Robb Matzke * Thursday, October 9, 1997 @@ -592,14 +592,14 @@ done: *------------------------------------------------------------------------- */ /* ARGSUSED */ -static herr_t +static htri_t H5D_istore_found(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, haddr_t addr, const void *_lt_key, void *_udata) { H5D_chunk_ud_t *udata = (H5D_chunk_ud_t *) _udata; const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *) _lt_key; unsigned u; - herr_t ret_value = SUCCEED; /* Return value */ + htri_t ret_value = TRUE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_found) @@ -612,7 +612,7 @@ 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.offset[u] >= lt_key->offset[u] + udata->common.mesg->u.chunk.dim[u]) - HGOTO_DONE(FAIL) + HGOTO_DONE(FALSE) /* Initialize return values */ HDassert(lt_key->nbytes > 0); @@ -971,12 +971,12 @@ done: * *------------------------------------------------------------------------- */ -static haddr_t +static herr_t H5D_istore_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata) { - haddr_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_idx_get_addr) + FUNC_ENTER_NOAPI_NOINIT(H5D_istore_idx_get_addr) HDassert(idx_info); HDassert(idx_info->f); @@ -984,23 +984,9 @@ H5D_istore_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udat HDassert(idx_info->layout->u.chunk.ndims > 0); HDassert(udata); - /* Go get the chunk information */ - if(H5B_find(idx_info->f, idx_info->dxpl_id, H5B_ISTORE, idx_info->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); - - HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, HADDR_UNDEF, "Can't locate chunk info") -#else /* OLD_WAY */ - HGOTO_DONE(HADDR_UNDEF) -#endif /* OLD_WAY */ - } /* end if */ - - /* Success! Set the return value */ - ret_value = udata->addr; + /* Go get the chunk information from the B-tree */ + if(H5B_find(idx_info->f, idx_info->dxpl_id, H5B_ISTORE, idx_info->layout->u.chunk.addr, udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info") done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c index 2cc6a3d..99ad001 100644 --- a/src/H5Dmpio.c +++ b/src/H5Dmpio.c @@ -848,6 +848,7 @@ H5D_link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type * equivalent of compressed contiguous datasets - QAK] */ if(total_chunks == 1) { + H5D_chunk_ud_t udata; /* User data for querying chunk info */ hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk in file dataset's dataspace */ H5SL_node_t *chunk_node; /* Pointer to chunk node for selection */ H5S_t *fspace; /* Dataspace describing chunk & selection in it */ @@ -858,8 +859,9 @@ H5D_link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type HDmemset(coords, 0, sizeof(coords)); /* Look up address of chunk */ - if(HADDR_UNDEF == (ctg_store.contig.dset_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, coords, NULL))) + if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, coords, &udata) < 0) HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list") + ctg_store.contig.dset_addr = udata.addr; /* Check for this process having selection in this chunk */ chunk_node = H5SL_first(fm->sel_chunks); @@ -1207,7 +1209,6 @@ if(H5DEBUG(D)) void *chunk; /* Pointer to the data chunk in cache */ uint32_t accessed_bytes; /* Total accessed size in a chunk */ unsigned idx_hint = 0; /* Cache index hint */ - haddr_t caddr; /* Address of the cached chunk */ /* Switch to independent I/O */ if(last_xfer_mode != H5FD_MPIO_INDEPENDENT) { @@ -1219,11 +1220,11 @@ if(H5DEBUG(D)) /* Load the chunk into cache. But if the whole chunk is written, * simply allocate space instead of load the chunk. */ - if(HADDR_UNDEF == (caddr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata))) + if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0) HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list") /* Load the chunk into cache and lock it. */ - if(H5D_chunk_cacheable(io_info, caddr)) { + if(H5D_chunk_cacheable(io_info, udata.addr)) { hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */ /* Compute # of bytes accessed in chunk */ @@ -1246,7 +1247,7 @@ if(H5DEBUG(D)) } /* end if */ else { /* Set up the storage address information for this chunk */ - ctg_store.contig.dset_addr = caddr; + ctg_store.contig.dset_addr = udata.addr; /* No chunk cached */ chunk = NULL; @@ -1396,7 +1397,6 @@ if(H5DEBUG(D)) { /* Iterate through chunks to be operated on */ while(chunk_node) { H5D_chunk_info_t *chunk_info; /* chunk information */ - haddr_t chunk_addr; /* Address of chunk in file */ H5D_chunk_ud_t udata; /* B-tree pass-through */ hbool_t make_ind, make_coll; /* Flags to indicate that the MPI mode should change */ @@ -1434,8 +1434,8 @@ if(H5DEBUG(D)) { #endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */ /* Retrieve the chunk's address */ - if(HADDR_UNDEF == (chunk_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata))) - HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list") + if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0) + HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list") /* Independent I/O */ if(make_ind) { @@ -1449,7 +1449,7 @@ if(H5DEBUG(D)) { HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O") /* Load the chunk into cache and lock it. */ - if(H5D_chunk_cacheable(io_info, chunk_addr)) { + if(H5D_chunk_cacheable(io_info, udata.addr)) { hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */ /* Compute # of bytes accessed in chunk */ @@ -1472,7 +1472,7 @@ if(H5DEBUG(D)) { } /* end if */ else { /* Set up the storage address information for this chunk */ - ctg_store.contig.dset_addr = chunk_addr; + ctg_store.contig.dset_addr = udata.addr; /* No chunk cached */ chunk = NULL; @@ -1499,7 +1499,7 @@ if(H5DEBUG(D)) { } /* end if */ else { /*collective I/O */ /* Set up the storage address information for this chunk */ - ctg_store.contig.dset_addr = chunk_addr; + ctg_store.contig.dset_addr = udata.addr; if(H5D_inter_collective_io(&ctg_io_info, type_info, chunk_info->fspace, chunk_info->mspace) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO") @@ -1743,8 +1743,12 @@ if(H5DEBUG(D)) HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list") if(many_chunk_opt == H5D_OBTAIN_ONE_CHUNK_ADDR_IND) { - if(HADDR_UNDEF == (chunk_addr = H5D_chunk_get_addr(io_info->dset, io_info->dxpl_id, chunk_info->coords, NULL))) + H5D_chunk_ud_t udata; /* User data for querying chunk info */ + + /* Get address of chunk */ + if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0) HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list") + chunk_addr = udata.addr; } /* end if */ else chunk_addr = total_chunk_addr_array[chunk_info->index]; diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index f6732ff..09a3c2c 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -264,7 +264,7 @@ typedef herr_t (*H5D_chunk_init_func_t)(const H5D_chk_idx_info_t *idx_info); typedef herr_t (*H5D_chunk_create_func_t)(const H5D_chk_idx_info_t *idx_info); typedef herr_t (*H5D_chunk_insert_func_t)(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata); -typedef haddr_t (*H5D_chunk_get_addr_func_t)(const H5D_chk_idx_info_t *idx_info, +typedef herr_t (*H5D_chunk_get_addr_func_t)(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata); typedef int (*H5D_chunk_iterate_func_t)(const H5D_chk_idx_info_t *idx_info, H5D_chunk_cb_func_t chunk_cb, void *chunk_udata); @@ -564,7 +564,7 @@ H5_DLL hbool_t H5D_chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr); H5_DLL herr_t H5D_chunk_cinfo_cache_reset(H5D_chunk_cached_t *last); H5_DLL herr_t H5D_chunk_create(H5D_t *dset /*in,out*/, hid_t dxpl_id); H5_DLL herr_t H5D_chunk_init(H5F_t *f, hid_t dxpl_id, const H5D_t *dset); -H5_DLL haddr_t H5D_chunk_get_addr(const H5D_t *dset, hid_t dxpl_id, +H5_DLL herr_t H5D_chunk_get_info(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset, H5D_chunk_ud_t *udata); H5_DLL void *H5D_chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t relax, unsigned *idx_hint/*in,out*/); @@ -29,6 +29,7 @@ #include "H5FDprivate.h" /* File drivers */ #include "H5Gprivate.h" /* Groups */ #include "H5Iprivate.h" /* IDs */ +#include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ #include "H5SMprivate.h" /* Shared Object Header Messages */ @@ -321,11 +322,11 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref) 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->meta_aggr.alloc_size)) < 0) + if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->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->sdata_aggr.alloc_size)) < 0) + if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->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") @@ -797,31 +798,31 @@ done: htri_t H5Fis_hdf5(const char *name) { - H5FD_t *file = NULL; - htri_t ret_value; + H5FD_t *file = NULL; /* Low-level file struct */ + htri_t ret_value; /* Return value */ FUNC_ENTER_API(H5Fis_hdf5, FAIL) H5TRACE1("t", "*s", name); /* Check args and all the boring stuff. */ - if (!name || !*name) + if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified") /* Open the file at the virtual file layer */ - if (NULL==(file=H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF))) + if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF))) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file") /* The file is an hdf5 file if the hdf5 file signature can be found */ - ret_value = (HADDR_UNDEF!=H5F_locate_signature(file, H5AC_ind_dxpl_id)); + ret_value = (HADDR_UNDEF != H5F_locate_signature(file, H5AC_ind_dxpl_id)); done: /* Close the file */ - if (file) - if(H5FD_close(file) < 0 && ret_value>=0) + if(file) + if(H5FD_close(file) < 0 && ret_value >= 0) HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file") FUNC_LEAVE_API(ret_value) -} +} /* end H5Fis_hdf5() */ /*------------------------------------------------------------------------- @@ -879,17 +880,20 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) } /* end if */ else { unsigned super_vers = HDF5_SUPERBLOCK_VERSION_DEF; /* Superblock version for file */ - H5P_genplist_t *plist; /* Property list */ + H5P_genplist_t *plist; /* Property list */ + size_t u; /* Local index variable */ HDassert(lf != NULL); if(NULL == (f->shared = H5FL_CALLOC(H5F_file_t))) HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared file structure") - f->shared->super_addr = HADDR_UNDEF; f->shared->base_addr = HADDR_UNDEF; f->shared->extension_addr = HADDR_UNDEF; f->shared->sohm_addr = HADDR_UNDEF; f->shared->sohm_vers = HDF5_SHAREDHEADER_VERSION; + for(u = 0; u < NELMTS(f->shared->fs_addr); u++) + f->shared->fs_addr[u] = HADDR_UNDEF; f->shared->driver_addr = HADDR_UNDEF; + f->shared->accum.loc = HADDR_UNDEF; f->shared->lf = lf; /* @@ -935,11 +939,23 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get sieve buffer size") 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") + if(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get metadata cache size") + f->shared->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA; + if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' cache size") + f->shared->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA; /* 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") + if(H5FD_get_feature_flags(lf, &f->shared->feature_flags) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get feature flags from VFD") + if(H5FD_get_fs_type_map(lf, f->shared->fs_type_map) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get free space type mapping from VFD") + if(H5MF_init_merge_flags(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "problem initializing free space merge flags") /* Bump superblock version if we are to use the latest version of the format */ if(f->shared->latest_format) @@ -1073,6 +1089,9 @@ H5F_dest(H5F_t *f, hid_t dxpl_id) if(H5AC_dest(f, dxpl_id)) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") + if(H5F_accum_reset(f) < 0) + /* Push error, but keep going*/ + HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") if(H5FO_dest(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") @@ -1765,6 +1784,18 @@ 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") + /* If we will be closing the file, we should release the free space + * information now (needs to happen before truncating the file and + * before the metadata cache is shut down, since the free space manager is + * holding some data structures in memory and also because releasing free + * space can shrink the file's 'eoa' value) + */ + if(flags & H5F_FLUSH_CLOSING) { + /* Shutdown file free space manager(s) */ + if(H5MF_close(f, dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info") + } /* end if */ + /* flush (and invalidate, if requested) the entire metadata cache */ H5AC_flags = 0; if((flags & H5F_FLUSH_INVALIDATE) != 0 ) @@ -1772,23 +1803,21 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags) if(H5AC_flush(f, dxpl_id, H5AC_flags) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache") - /* - * If we are invalidating everything (which only happens just before - * the file closes), release the unused portion of the metadata and - * "small data" blocks back to the free lists in the file. + /* Truncate the file to the current allocated size */ + /* (needs to happen before superblock write, since the 'eoa' value is + * written in superblock -QAK) */ - if(flags & H5F_FLUSH_INVALIDATE) { - 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") - - 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 */ + if(H5FD_truncate(f->shared->lf, dxpl_id, (unsigned)((flags & H5F_FLUSH_CLOSING) > 0)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level truncate failed") /* Write the superblock to disk */ if(H5F_super_write(f, dxpl_id) != SUCCEED) HGOTO_ERROR(H5E_CACHE, H5E_WRITEERROR, FAIL, "unable to write superblock to file") + /* Flush out the metadata accumulator */ + if(H5F_accum_flush(f, dxpl_id) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator") + /* Flush file buffers to disk. */ if(H5FD_flush(f->shared->lf, dxpl_id, (unsigned)((flags & H5F_FLUSH_CLOSING) > 0)) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed") @@ -2004,7 +2033,7 @@ H5F_try_close(H5F_t *f) */ if(f->intent&H5F_ACC_RDWR) { /* Flush and destroy all caches */ - if(H5F_flush(f, H5AC_dxpl_id, H5F_SCOPE_LOCAL, H5C__NO_FLAGS_SET) < 0) + if(H5F_flush(f, H5AC_dxpl_id, H5F_SCOPE_LOCAL, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache") } /* end if */ @@ -2138,410 +2167,37 @@ done: * Programmer: James Laird * August 23, 2006 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5Fget_intent(hid_t file_id, unsigned *intent_flags) { - H5F_t * file = NULL; herr_t ret_value = SUCCEED; FUNC_ENTER_API(H5Fget_intent, FAIL) H5TRACE2("e", "i*Iu", file_id, intent_flags); - if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") - /* If no intent flags were passed in, exit quietly */ - if(!intent_flags) - HGOTO_DONE(SUCCEED) + if(intent_flags) { + H5F_t * file; /* Pointer to file structure */ - *intent_flags = H5F_get_intent(file); + /* Get the internal file structure */ + if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") - /* HDF5 uses some flags internally that users don't know about. - * Simplify things for them so that they get one of H5F_ACC_RDWR - * or H5F_ACC_RDONLY. - */ - if(*intent_flags & H5F_ACC_RDWR) - *intent_flags = H5F_ACC_RDWR; - else - *intent_flags = H5F_ACC_RDONLY; + /* HDF5 uses some flags internally that users don't know about. + * Simplify things for them so that they only get either H5F_ACC_RDWR + * or H5F_ACC_RDONLY. + */ + if(H5F_INTENT(file) & H5F_ACC_RDWR) + *intent_flags = H5F_ACC_RDWR; + else + *intent_flags = H5F_ACC_RDONLY; + } /* end if */ done: FUNC_LEAVE_API(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5F_get_intent - * - * Purpose: Quick and dirty routine to retrieve the file's 'intent' flags - * (Mainly added to stop non-file routines from poking about in the - * H5F_t data structure) - * - * Return: 'intent' on success/abort on failure (shouldn't fail) - * - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> - * September 29, 2000 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -unsigned -H5F_get_intent(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_intent) - - HDassert(f); - - FUNC_LEAVE_NOAPI(f->intent) -} /* end H5F_get_intent() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_get_extpath - * - * Purpose: Retrieve the file's 'extpath' flags - * This is used by H5L_extern_traverse() to retrieve the main file's location - * when searching the target file. - * - * Return: 'extpath' on success/abort on failure (shouldn't fail) - * - * Programmer: Vailin Choi, April 2, 2008 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -char * -H5F_get_extpath(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_extpath) - - HDassert(f); - - FUNC_LEAVE_NOAPI(f->extpath) -} /* end H5F_get_extpath() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_sizeof_addr - * - * Purpose: Quick and dirty routine to retrieve the size of the file's size_t - * (Mainly added to stop non-file routines from poking about in the - * H5F_t data structure) - * - * Return: 'sizeof_addr' on success/abort on failure (shouldn't fail) - * - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> - * September 29, 2000 - * - * Modifications: - * - * Raymond Lu, Oct 14, 2001 - * Changed to generic property list. - * - *------------------------------------------------------------------------- - */ -size_t -H5F_sizeof_addr(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_addr) - - assert(f); - assert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->sizeof_addr) -} - - -/*------------------------------------------------------------------------- - * Function: H5F_sizeof_size - * - * Purpose: Quick and dirty routine to retrieve the size of the file's off_t - * (Mainly added to stop non-file routines from poking about in the - * H5F_t data structure) - * - * Return: 'sizeof_size' on success/abort on failure (shouldn't fail) - * - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> - * September 29, 2000 - * - *------------------------------------------------------------------------- - */ -size_t -H5F_sizeof_size(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_size) - - assert(f); - assert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->sizeof_size) -} /* H5F_sizeof_size() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_sym_leaf_k - * - * Purpose: Replaced a macro to retrieve the symbol table leaf size, - * now that the generic properties are being used to store - * the values. - * - * Return: Success: Non-negative, and the symbol table leaf size is - * returned. - * - * Failure: Negative (should not happen) - * - * Programmer: Raymond Lu - * slu@ncsa.uiuc.edu - * Oct 14 2001 - * - *------------------------------------------------------------------------- - */ -unsigned -H5F_sym_leaf_k(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sym_leaf_k) - - assert(f); - assert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->sym_leaf_k) -} /* end H5F_sym_leaf_k() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_Kvalue - * - * Purpose: Replaced a macro to retrieve a B-tree key value for a certain - * type, now that the generic properties are being used to store - * the B-tree values. - * - * Return: Success: Non-negative, and the B-tree key value is - * returned. - * - * Failure: Negative (should not happen) - * - * Programmer: Raymond Lu - * slu@ncsa.uiuc.edu - * Oct 14 2001 - * - *------------------------------------------------------------------------- - */ -unsigned -H5F_Kvalue(const H5F_t *f, const H5B_class_t *type) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_Kvalue) - - assert(f); - assert(f->shared); - assert(type); - - FUNC_LEAVE_NOAPI(f->shared->btree_k[type->id]) -} /* end H5F_Kvalue() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_rdcc_nelmts - * - * Purpose: Replaced a macro to retrieve the raw data cache number of elments, - * now that the generic properties are being used to store - * the values. - * - * Return: Success: Non-negative, and the raw data cache number of - * of elemnts is returned. - * - * Failure: Negative (should not happen) - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jun 1 2004 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -size_t -H5F_rdcc_nelmts(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nelmts) - - assert(f); - assert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->rdcc_nelmts) -} /* end H5F_rdcc_nelmts() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_rdcc_nbytes - * - * Purpose: Replaced a macro to retrieve the raw data cache number of bytes, - * now that the generic properties are being used to store - * the values. - * - * Return: Success: Non-negative, and the raw data cache number of - * of bytes is returned. - * - * Failure: Negative (should not happen) - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jun 1 2004 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -size_t -H5F_rdcc_nbytes(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nbytes) - - assert(f); - assert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->rdcc_nbytes) -} /* end H5F_rdcc_nbytes() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_rdcc_w0 - * - * Purpose: Replaced a macro to retrieve the raw data cache 'w0' value - * now that the generic properties are being used to store - * the values. - * - * Return: Success: Non-negative, and the raw data cache 'w0' value - * is returned. - * - * Failure: Negative (should not happen) - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jun 2 2004 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -double -H5F_rdcc_w0(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_w0) - - assert(f); - assert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->rdcc_w0) -} /* end H5F_rdcc_w0() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_has_feature - * - * Purpose: Check if a file has a particular feature enabled - * - * Return: Success: Non-negative - TRUE or FALSE - * Failure: Negative (should not happen) - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * May 31 2004 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hbool_t -H5F_has_feature(const H5F_t *f, unsigned feature) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_has_feature) - - assert(f); - assert(f->shared); - - FUNC_LEAVE_NOAPI((hbool_t)(f->shared->lf->feature_flags&feature)) -} /* end H5F_has_feature() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_get_driver_id - * - * Purpose: Quick and dirty routine to retrieve the file's 'driver_id' value - * (Mainly added to stop non-file routines from poking about in the - * H5F_t data structure) - * - * Return: 'driver_id' on success/abort on failure (shouldn't fail) - * - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> - * October 10, 2000 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hid_t -H5F_get_driver_id(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_driver_id) - - assert(f); - assert(f->shared); - assert(f->shared->lf); - - FUNC_LEAVE_NOAPI(f->shared->lf->driver_id) -} - - -/*------------------------------------------------------------------------- - * Function: H5F_get_fileno - * - * Purpose: Quick and dirty routine to retrieve the file's 'fileno' value - * (Mainly added to stop non-file routines from poking about in the - * H5F_t data structure) - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> - * March 27, 2002 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_get_fileno(const H5F_t *f, unsigned long *filenum) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI(H5F_get_fileno, FAIL) - - 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) - HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_get_fileno() */ +} /* end H5Fget_intent() */ /*------------------------------------------------------------------------- @@ -2584,35 +2240,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_get_base_addr - * - * Purpose: Quick and dirty routine to retrieve the file's 'base_addr' value - * (Mainly added to stop non-file routines from poking about in the - * H5F_t data structure) - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Raymond Lu <slu@ncsa.uiuc.edu> - * December 20, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -haddr_t -H5F_get_base_addr(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_base_addr) - - assert(f); - assert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->base_addr) -} /* end H5F_get_base_addr() */ - - -/*------------------------------------------------------------------------- * Function: H5F_get_eoa * * Purpose: Quick and dirty routine to retrieve the file's 'eoa' value @@ -2622,314 +2249,26 @@ H5F_get_base_addr(const H5F_t *f) * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> * June 1, 2004 * - * Modifications: - * *------------------------------------------------------------------------- */ haddr_t -H5F_get_eoa(const H5F_t *f) +H5F_get_eoa(const H5F_t *f, H5FD_mem_t type) { haddr_t ret_value; FUNC_ENTER_NOAPI(H5F_get_eoa, HADDR_UNDEF) - assert(f); - assert(f->shared); + HDassert(f); + HDassert(f->shared); /* Dispatch to driver */ - if (HADDR_UNDEF==(ret_value=H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT))) + if(HADDR_UNDEF == (ret_value = H5FD_get_eoa(f->shared->lf, type))) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_get_eoa() */ -#ifdef H5_HAVE_PARALLEL - -/*------------------------------------------------------------------------- - * Function: H5F_mpi_get_rank - * - * Purpose: Retrieves the rank of an MPI process. - * - * Return: Success: The rank (non-negative) - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * Friday, January 30, 2004 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -int -H5F_mpi_get_rank(const H5F_t *f) -{ - int ret_value; - - FUNC_ENTER_NOAPI(H5F_mpi_get_rank, FAIL) - - assert(f && f->shared); - - /* Dispatch to driver */ - if ((ret_value=H5FD_mpi_get_rank(f->shared->lf)) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_rank request failed") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_mpi_get_rank() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_mpi_get_comm - * - * Purpose: Retrieves the file's communicator - * - * Return: Success: The communicator (non-negative) - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * Friday, January 30, 2004 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -MPI_Comm -H5F_mpi_get_comm(const H5F_t *f) -{ - MPI_Comm ret_value; - - FUNC_ENTER_NOAPI(H5F_mpi_get_comm, MPI_COMM_NULL) - - assert(f && f->shared); - - /* Dispatch to driver */ - if ((ret_value=H5FD_mpi_get_comm(f->shared->lf))==MPI_COMM_NULL) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_COMM_NULL, "driver get_comm request failed") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_mpi_get_comm() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_mpi_get_size - * - * Purpose: Retrieves the size of an MPI process. - * - * Return: Success: The size (positive) - * - * Failure: Negative - * - * Programmer: John Mainzer - * Friday, May 6, 2005 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -int -H5F_mpi_get_size(const H5F_t *f) -{ - int ret_value; - - FUNC_ENTER_NOAPI(H5F_mpi_get_size, FAIL) - - assert(f && f->shared); - - /* Dispatch to driver */ - if ((ret_value=H5FD_mpi_get_size(f->shared->lf)) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_size request failed") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_mpi_get_size() */ -#endif /* H5_HAVE_PARALLEL */ - - -/*------------------------------------------------------------------------- - * Function: H5F_grp_btree_shared - * - * Purpose: Replaced a macro to retrieve the shared B-tree node info - * now that the generic properties are being used to store - * the values. - * - * Return: Success: Non-void, and the shared B-tree node info - * is returned. - * - * Failure: void (should not happen) - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jul 5 2004 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5RC_t * -H5F_grp_btree_shared(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_grp_btree_shared) - - assert(f); - assert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->grp_btree_shared) -} /* end H5F_grp_btree_shared() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_sieve_buf_size - * - * Purpose: Replaced a macro to retrieve the dataset sieve buffer size - * now that the generic properties are being used to store - * the values. - * - * Return: Success: Non-void, and the dataset sieve buffer size - * is returned. - * - * Failure: void (should not happen) - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jul 8 2005 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -size_t -H5F_sieve_buf_size(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sieve_buf_size) - - assert(f); - assert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->sieve_buf_size) -} /* end H5F_sieve_buf_size() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_gc_ref - * - * Purpose: Replaced a macro to retrieve the "garbage collect - * references flag" now that the generic properties are being used - * to store the values. - * - * Return: Success: The "garbage collect references flag" - * is returned. - * - * Failure: (should not happen) - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jul 8 2005 - * - *------------------------------------------------------------------------- - */ -unsigned -H5F_gc_ref(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_gc_ref) - - HDassert(f); - HDassert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->gc_ref) -} /* end H5F_gc_ref() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_get_fcpl - * - * Purpose: Retrieve the value of a file's FCPL. - * - * Return: Success: The FCPL for the file. - * - * Failure: ? (should not happen) - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * May 25 2005 - * - *------------------------------------------------------------------------- - */ -hid_t -H5F_get_fcpl(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fcpl) - - assert(f); - assert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->fcpl_id) -} /* end H5F_get_fcpl() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_use_latest_format - * - * Purpose: Retrieve the 'use the latest version of the format' flag for - * the file. - * - * Return: Success: Non-negative, the 'use the latest format' flag - * - * Failure: (can't happen) - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Oct 2 2006 - * - *------------------------------------------------------------------------- - */ -hbool_t -H5F_use_latest_format(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_use_latest_format) - - HDassert(f); - HDassert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->latest_format) -} /* end H5F_use_latest_format() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_get_fc_degree - * - * Purpose: Retrieve the 'file close degree' for the file. - * - * Return: Success: Non-negative, the 'file close degree' - * - * Failure: (can't happen) - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Mar 5 2007 - * - *------------------------------------------------------------------------- - */ -H5F_close_degree_t -H5F_get_fc_degree(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fc_degree) - - HDassert(f); - HDassert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->fc_degree) -} /* end H5F_get_fc_degree() */ - /*------------------------------------------------------------------------- * Function: H5F_incr_nopen_objs @@ -2986,148 +2325,6 @@ H5F_decr_nopen_objs(H5F_t *f) /*------------------------------------------------------------------------- - * Function: H5F_store_msg_crt_idx - * - * Purpose: Retrieve the 'store message creation index' flag for the file. - * - * Return: Success: Non-negative, the 'store message creation index' flag - * - * Failure: (can't happen) - * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Mar 6 2007 - * - *------------------------------------------------------------------------- - */ -hbool_t -H5F_store_msg_crt_idx(const H5F_t *f) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_store_msg_crt_idx) - - HDassert(f); - HDassert(f->shared); - - FUNC_LEAVE_NOAPI(f->shared->store_msg_crt_idx) -} /* end H5F_store_msg_crt_idx() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_block_read - * - * Purpose: Reads some data from a file/server/etc into a buffer. - * The data is contiguous. The address is relative to the base - * address for the file. - * - * Errors: - * IO READERROR Low-level read failed. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 10 1997 - * - * Modifications: - * Albert Cheng, 1998-06-02 - * Added XFER_MODE argument - * - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Robb Matzke, 1999-08-02 - * Modified to use the virtual file layer. The data transfer - * property list is passed in by object ID since that's how the - * virtual file layer needs it. - *------------------------------------------------------------------------- - */ -herr_t -H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, hid_t dxpl_id, - void *buf/*out*/) -{ - haddr_t abs_addr; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_block_read, FAIL) - - assert (f); - assert (f->shared); - assert(size<SIZET_MAX); - assert (buf); - - /* convert the relative address to an absolute address */ - abs_addr = f->shared->base_addr + addr; - - /* Read the data */ - if(H5FD_read(f->shared->lf, type, dxpl_id, abs_addr, size, buf) < 0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5F_block_write - * - * Purpose: Writes some data from memory to a file/server/etc. The - * data is contiguous. The address is relative to the base - * address. - * - * Errors: - * IO WRITEERROR Low-level write failed. - * IO WRITEERROR No write intent. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 10 1997 - * - * Modifications: - * Albert Cheng, 1998-06-02 - * Added XFER_MODE argument - * - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Robb Matzke, 1999-08-02 - * Modified to use the virtual file layer. The data transfer - * property list is passed in by object ID since that's how the - * virtual file layer needs it. - *------------------------------------------------------------------------- - */ -herr_t -H5F_block_write(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, - hid_t dxpl_id, const void *buf) -{ - haddr_t abs_addr; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_block_write, FAIL) - - assert (f); - assert (f->shared); - assert (size<SIZET_MAX); - assert (buf); - - if (0==(f->intent & H5F_ACC_RDWR)) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "no write intent") - - /* Convert the relative address to an absolute address */ - abs_addr = f->shared->base_addr + addr; - - /* Write the data */ - if (H5FD_write(f->shared->lf, type, dxpl_id, abs_addr, size, buf)) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- * Function: H5F_addr_encode * * Purpose: Encodes an address into the buffer pointed to by *PP and @@ -3234,7 +2431,7 @@ H5F_addr_decode(const H5F_t *f, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*o hssize_t H5Fget_freespace(hid_t file_id) { - H5F_t *file=NULL; /* File object for file ID */ + H5F_t *file; /* File object for file ID */ hssize_t ret_value; /* Return value */ FUNC_ENTER_API(H5Fget_freespace, FAIL) @@ -3245,7 +2442,7 @@ H5Fget_freespace(hid_t file_id) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") /* Go get the actual amount of free space in the file */ - if((ret_value = H5FD_get_freespace(file->shared->lf)) < 0) + if((ret_value = H5MF_get_freespace(file, H5AC_ind_dxpl_id)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to check free space for file") done: @@ -3275,19 +2472,19 @@ herr_t H5Fget_filesize(hid_t file_id, hsize_t *size) { H5F_t *file; /* File object for file ID */ - haddr_t eof; - herr_t ret_value = SUCCEED; /* Return value */ + haddr_t eof; /* End of file address */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Fget_filesize, FAIL) H5TRACE2("e", "i*h", file_id, size); /* Check args */ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") /* Go get the actual file size */ - if((eof = H5FDget_eof(file->shared->lf)) == HADDR_UNDEF) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size") + if(HADDR_UNDEF == (eof = H5FDget_eof(file->shared->lf))) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size") *size = (hsize_t)eof; @@ -62,9 +62,6 @@ /* Local Macros */ /****************/ -/* Metadata accumulator controls */ -#define H5FD_ACCUM_THROTTLE 8 -#define H5FD_ACCUM_THRESHOLD 2048 /******************/ /* Local Typedefs */ @@ -1053,23 +1050,23 @@ done: H5FD_t * H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) { - H5FD_class_t *driver; - H5FD_t *file = NULL; - hid_t driver_id = -1; - hsize_t meta_block_size = 0; - hsize_t sdata_block_size = 0; - H5P_genplist_t *plist; /* Property list pointer */ - H5FD_t *ret_value; + H5FD_class_t *driver; /* VFD for file */ + H5FD_t *file = NULL; /* VFD file struct */ + hid_t driver_id = -1; /* VFD ID */ + H5P_genplist_t *plist; /* Property list pointer */ + H5FD_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5FD_open, NULL) - /* Get file access property list */ - if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") - + /* Sanity check */ if(0 == maxaddr) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "zero format address range") + /* Get file access property list */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); + + /* Get the VFD to open the file with */ if(H5P_get(plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get driver ID") @@ -1094,16 +1091,6 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver") file->cls = driver; file->maxaddr = 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->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->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") if(H5P_get(plist, H5F_ACS_ALIGN_NAME, &(file->alignment)) < 0) @@ -1120,6 +1107,10 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) } /* end if */ file->fileno = file_serial_no; + /* Start with base address set to 0 */ + /* (This will be changed later, when the superblock is located) */ + file->base_addr = 0; + /* Set return value */ ret_value = file; @@ -1203,10 +1194,6 @@ H5FD_close(H5FD_t *file) /* check args */ HDassert(file && file->cls); - /* Free the freelist */ - if(H5FD_free_freelist(file) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't release file space free list") - /* Prepare to close file by clearing all public fields */ driver = file->cls; if(H5I_dec_ref(file->driver_id, FALSE) < 0) @@ -1423,6 +1410,8 @@ done: * Tuesday, July 27, 1999 * * Modifications: + * Vailin Choi, 29th July 2008 + * Two more parameters were added to H5FD_alloc() for handling alignment * *------------------------------------------------------------------------- */ @@ -1448,12 +1437,15 @@ H5FDalloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, HADDR_UNDEF, "not a data transfer property list") /* Do the real work */ - if(HADDR_UNDEF == (ret_value = H5FD_alloc(file, type, dxpl_id, size))) + if(HADDR_UNDEF == (ret_value = H5FD_alloc(file, dxpl_id, type, size, NULL, NULL))) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "unable to allocate file memory") + /* (Note compensating for base address subtraction in internal routine) */ + ret_value += file->base_addr; + done: FUNC_LEAVE_API(ret_value) -} +} /* end H5FDalloc() */ /*------------------------------------------------------------------------- @@ -1497,7 +1489,8 @@ H5FDfree(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t siz HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list") /* Do the real work */ - if(H5FD_free(file, type, dxpl_id, addr, size) < 0) + /* (Note compensating for base address addition in internal routine) */ + if(H5FD_free(file, dxpl_id, type, addr - file->base_addr, size) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "file deallocation request failed") done: @@ -1506,65 +1499,17 @@ done: /*------------------------------------------------------------------------- - * Function: H5FDrealloc - * - * Purpose: Changes the size of an allocated chunk of memory, possibly - * also changing its location in the file. - * - * Return: Success: New address of the block of memory, not - * necessarily the same as the original address. - * - * Failure: HADDR_UNDEF - * - * Programmer: Robb Matzke - * Tuesday, August 3, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -haddr_t -H5FDrealloc(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 ret_value = HADDR_UNDEF; - - FUNC_ENTER_API(H5FDrealloc, HADDR_UNDEF) - H5TRACE6("a", "*xMtiahh", file, type, dxpl_id, old_addr, old_size, new_size); - - /* Check args */ - if(H5P_DEFAULT == dxpl_id) - dxpl_id = H5P_DATASET_XFER_DEFAULT; - else - if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, HADDR_UNDEF, "not a data transfer property list") - - if(HADDR_UNDEF == (ret_value = H5FD_realloc(file, type, dxpl_id, old_addr, old_size, new_size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "file reallocation request failed") - -done: - FUNC_LEAVE_API(ret_value) -} /* end H5FDrealloc() */ - - -/*------------------------------------------------------------------------- * Function: H5FDget_eoa * * Purpose: Returns the address of the first byte after the last * allocated memory in the file. * * Return: Success: First byte after allocated memory. - * * Failure: HADDR_UNDEF * * Programmer: Robb Matzke * Friday, July 30, 1999 * - * Modifications: - * Raymond Lu - * 21 Dec. 2006 - * Added the parameter TYPE. It's only used for MULTI driver. - * *------------------------------------------------------------------------- */ haddr_t @@ -1578,52 +1523,19 @@ H5FDget_eoa(H5FD_t *file, H5FD_mem_t type) /* Check args */ if(!file || !file->cls) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file pointer") - if(type<H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES) + if(type < H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file type") /* The real work */ - if(HADDR_UNDEF==(ret_value=H5FD_get_eoa(file, type))) + if(HADDR_UNDEF == (ret_value = H5FD_get_eoa(file, type))) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "file get eoa request failed") -done: - FUNC_LEAVE_API(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5FD_get_eoa - * - * Purpose: Private version of H5FDget_eoa() - * - * Return: Success: First byte after allocated memory. - * - * Failure: HADDR_UNDEF - * - * Programmer: Robb Matzke - * Wednesday, August 4, 1999 - * - * Modifications: - * Raymond Lu - * 21 Dec. 2006 - * Added the parameter TYPE. It's only used for MULTI driver. - * - *------------------------------------------------------------------------- - */ -haddr_t -H5FD_get_eoa(const H5FD_t *file, H5FD_mem_t type) -{ - haddr_t ret_value; - - FUNC_ENTER_NOAPI(H5FD_get_eoa, HADDR_UNDEF) - assert(file && file->cls); - - /* Dispatch to driver */ - if(HADDR_UNDEF==(ret_value=(file->cls->get_eoa)(file, type))) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed") + /* (Note compensating for base address subtraction in internal routine) */ + ret_value += file->base_addr; done: - FUNC_LEAVE_NOAPI(ret_value) -} + FUNC_LEAVE_API(ret_value) +} /* end H5FDget_eoa() */ /*------------------------------------------------------------------------- @@ -1643,23 +1555,17 @@ done: * and the driver didn't supply an allocation callback. * * Return: Success: Non-negative - * * Failure: Negative, no side effect * * Programmer: Robb Matzke * Friday, July 30, 1999 * - * Modifications: - * Raymond Lu - * 21 Dec. 2006 - * Added the parameter TYPE. It's only used for MULTI driver. - * *------------------------------------------------------------------------- */ herr_t H5FDset_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5FDset_eoa, FAIL) H5TRACE3("e", "*xMta", file, type, addr); @@ -1667,57 +1573,19 @@ H5FDset_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr) /* Check args */ if(!file || !file->cls) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer") - if(type<H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES) + if(type < H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file type") - - if(!H5F_addr_defined(addr) || addr>file->maxaddr) + if(!H5F_addr_defined(addr) || addr > file->maxaddr) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid end-of-address value") /* The real work */ - if(H5FD_set_eoa(file, type, addr) < 0) + /* (Note compensating for base address addition in internal routine) */ + if(H5FD_set_eoa(file, type, addr - file->base_addr) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "file set eoa request failed") done: FUNC_LEAVE_API(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5FD_set_eoa - * - * Purpose: Private version of H5FDset_eoa() - * - * Return: Success: Non-negative - * - * Failure: Negative, no side effect - * - * Programmer: Robb Matzke - * Wednesday, August 4, 1999 - * - * Modifications: - * Raymond Lu - * 21 Dec. 2006 - * Added the parameter TYPE. It's only used for MULTI driver. - * - *------------------------------------------------------------------------- - */ -herr_t -H5FD_set_eoa(H5FD_t *file, H5FD_mem_t UNUSED type, haddr_t addr) -{ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_set_eoa, FAIL) - - assert(file && file->cls); - assert(H5F_addr_defined(addr) && addr<=file->maxaddr); - - /* Dispatch to driver */ - if((file->cls->set_eoa)(file, type, addr) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver set_eoa request failed") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FDset_eoa() */ /*------------------------------------------------------------------------- @@ -1759,80 +1627,101 @@ H5FDget_eof(H5FD_t *file) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file pointer") /* The real work */ - if(HADDR_UNDEF==(ret_value=H5FD_get_eof(file))) + if(HADDR_UNDEF == (ret_value = H5FD_get_eof(file))) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "file get eof request failed") + /* (Note compensating for base address subtraction in internal routine) */ + ret_value += file->base_addr; + done: FUNC_LEAVE_API(ret_value) -} +} /* end H5FDget_eof() */ /*------------------------------------------------------------------------- - * Function: H5FD_get_eof + * Function: H5FD_get_maxaddr * * Purpose: Private version of H5FDget_eof() * - * Return: Success: The EOF address. - * + * Return: Success: The maximum address allowed in the file. * Failure: HADDR_UNDEF * - * Programmer: Robb Matzke - * Wednesday, August 4, 1999 - * - * Modifications: + * Programmer: Quincey Koziol + * Thursday, January 3, 2008 * *------------------------------------------------------------------------- */ haddr_t -H5FD_get_eof(const H5FD_t *file) +H5FD_get_maxaddr(const H5FD_t *file) { - haddr_t ret_value; + haddr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5FD_get_eof, HADDR_UNDEF) + FUNC_ENTER_NOAPI(H5FD_get_maxaddr, HADDR_UNDEF) - assert(file && file->cls); + HDassert(file); - /* Dispatch to driver */ - if(file->cls->get_eof) { - if(HADDR_UNDEF==(ret_value=(file->cls->get_eof)(file))) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eof request failed") - } else { - ret_value = file->maxaddr; - } + /* Set return value */ + ret_value = file->maxaddr; done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_get_maxaddr() */ /*------------------------------------------------------------------------- - * Function: H5FD_get_maxaddr + * Function: H5FD_get_feature_flags * - * Purpose: Private version of H5FDget_eof() + * Purpose: Retrieve the feature flags for the VFD * - * Return: Success: The maximum address allowed in the file. - * Failure: HADDR_UNDEF + * Return: Success: Non-negative + * Failure: Negative * * Programmer: Quincey Koziol - * Thursday, January 3, 2008 + * Tuesday, January 8, 2008 * *------------------------------------------------------------------------- */ -haddr_t -H5FD_get_maxaddr(const H5FD_t *file) +herr_t +H5FD_get_feature_flags(const H5FD_t *file, unsigned long *feature_flags) { - haddr_t ret_value; /* Return value */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_get_feature_flags) - FUNC_ENTER_NOAPI(H5FD_get_maxaddr, HADDR_UNDEF) + HDassert(file); + HDassert(feature_flags); + + /* Set feature flags to return */ + *feature_flags = file->feature_flags; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5FD_get_feature_flags() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_get_fs_type_map + * + * Purpose: Retrieve the free space type mapping for the VFD + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, January 17, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_get_fs_type_map(const H5FD_t *file, H5FD_mem_t *type_map) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_get_fs_type_map) HDassert(file); + HDassert(type_map); - /* Set return value */ - ret_value = file->maxaddr; + /* Copy free space type mapping */ + HDmemcpy(type_map, file->cls->fl_map, sizeof(file->cls->fl_map)); -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_get_maxaddr() */ + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5FD_get_fs_type_map() */ /*------------------------------------------------------------------------- @@ -1860,7 +1749,7 @@ herr_t H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, void *buf/*out*/) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5FDread, FAIL) H5TRACE6("e", "*xMtiazx", file, type, dxpl_id, addr, size, buf); @@ -1873,206 +1762,76 @@ H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size if(H5P_DEFAULT == dxpl_id) dxpl_id= H5P_DATASET_XFER_DEFAULT; else - if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER)) + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list") if(!buf) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null result buffer") /* Do the real work */ - if(H5FD_read(file, type, dxpl_id, addr, size, buf) < 0) + /* (Note compensating for base address addition in internal routine) */ + if(H5FD_read(file, dxpl_id, type, addr - file->base_addr, size, buf) < 0) HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file read request failed") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5FDread() */ /*------------------------------------------------------------------------- - * Function: H5FD_read + * Function: H5FDwrite * - * Purpose: Private version of H5FDread() + * Purpose: Writes SIZE bytes to FILE beginning at address ADDR according + * to the data transfer property list DXPL_ID (which may be the + * constant H5P_DEFAULT). The bytes to be written come from the + * buffer BUF. * * Return: Success: Non-negative * * Failure: Negative * * Programmer: Robb Matzke - * Wednesday, August 4, 1999 + * Thursday, July 29, 1999 * * Modifications: - * Albert Cheng, 2000-11-21 - * Disable the code that does early return when size==0 for - * Parallel mode since a collective call would require the process - * to continue on with "nothing" to transfer. * *------------------------------------------------------------------------- */ herr_t -H5FD_read(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, - void *buf/*out*/) +H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, + const void *buf) { - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_read, FAIL) - - assert(file && file->cls); - assert(H5I_GENPROP_LST==H5I_get_type(dxpl_id)); - assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - assert(buf); - -#ifndef H5_HAVE_PARALLEL - /* Do not return early for Parallel mode since the I/O could be a */ - /* collective transfer. */ - /* The no-op case */ - if(0==size) - HGOTO_DONE(SUCCEED) -#endif /* H5_HAVE_PARALLEL */ - - /* Check if this information is in the metadata accumulator */ - if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && type!=H5FD_MEM_DRAW) { - /* Current read overlaps with metadata accumulator */ - if(H5F_addr_overlap(addr,size,file->accum_loc,file->accum_size)) { - unsigned char *read_buf=(unsigned char *)buf; /* Pointer to the buffer being read in */ - size_t amount_read; /* Amount to read at a time */ -#ifndef NDEBUG - hsize_t tempamount_read; /* Amount to read at a time */ -#endif /* NDEBUG */ - hsize_t read_off; /* Offset to read from */ - - /* Double check that we aren't reading raw data */ - assert(type!=H5FD_MEM_DRAW); - - /* Read the part before the metadata accumulator */ - if(addr<file->accum_loc) { - /* Set the amount to read */ - H5_ASSIGN_OVERFLOW(amount_read,file->accum_loc-addr,hsize_t,size_t); - - /* Dispatch to driver */ - if((file->cls->read)(file, type, dxpl_id, addr, amount_read, read_buf) < 0) - HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed") - - /* Adjust the buffer, address & size */ - read_buf+=amount_read; - addr+=amount_read; - size-=amount_read; - } /* end if */ - - /* Copy the part overlapping the metadata accumulator */ - if(size>0 && (addr>=file->accum_loc && addr<(file->accum_loc+file->accum_size))) { - /* Set the offset to "read" from */ - read_off=addr-file->accum_loc; - - /* Set the amount to "read" */ -#ifndef NDEBUG - tempamount_read = file->accum_size-read_off; - H5_CHECK_OVERFLOW(tempamount_read,hsize_t,size_t); - amount_read = MIN(size, (size_t)tempamount_read); -#else /* NDEBUG */ - amount_read = MIN(size, (size_t)(file->accum_size-read_off)); -#endif /* NDEBUG */ - - /* Copy the data out of the buffer */ - HDmemcpy(read_buf,file->meta_accum+read_off,amount_read); - - /* Adjust the buffer, address & size */ - read_buf+=amount_read; - addr+=amount_read; - size-=amount_read; - } /* end if */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Read the part after the metadata accumulator */ - if(size>0 && addr>=(file->accum_loc+file->accum_size)) { - /* Dispatch to driver */ - if((file->cls->read)(file, type, dxpl_id, addr, size, read_buf) < 0) - HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed") + FUNC_ENTER_API(H5FDwrite, FAIL) + H5TRACE6("e", "*xMtiaz*x", file, type, dxpl_id, addr, size, buf); - /* Adjust the buffer, address & size */ - read_buf+=size; - addr+=size; - size-=size; - } /* end if */ + /* Check args */ + if(!file || !file->cls) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer") + /* Get the default dataset transfer property list if the user didn't provide one */ + if(H5P_DEFAULT == dxpl_id) + dxpl_id = H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list") + if(!buf) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null buffer") - /* Make certain we've read it all */ - assert(size==0); - } /* end if */ - /* Current read doesn't overlap with metadata accumulator, read it into accumulator */ - else { - /* Only update the metadata accumulator if it is not dirty or if - * we are allowed to write the accumulator out during reads (when - * it is dirty) - */ - if(file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA_READ || !file->accum_dirty) { - /* Flush current contents, if dirty */ - if(file->accum_dirty) { - if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0) - HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed") - - /* Reset accumulator dirty flag */ - file->accum_dirty=FALSE; - } /* end if */ - - /* Cache the new piece of metadata */ - /* Check if we need to resize the buffer */ - if(size>file->accum_buf_size) { - /* Grow the metadata accumulator buffer */ - if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") - - /* Note the new buffer size */ - file->accum_buf_size=size; - } /* end if */ - else { - /* Check if we should shrink the accumulator buffer */ - if(size<(file->accum_buf_size/H5FD_ACCUM_THROTTLE) && - file->accum_buf_size>H5FD_ACCUM_THRESHOLD) { - size_t new_size=(file->accum_buf_size/H5FD_ACCUM_THROTTLE); /* New size of accumulator buffer */ - - /* Shrink the accumulator buffer */ - if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,new_size))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") - - /* Note the new buffer size */ - file->accum_buf_size=new_size; - } /* end if */ - } /* end else */ - - /* Update accumulator information */ - file->accum_loc=addr; - file->accum_size=size; - file->accum_dirty=FALSE; - - /* Read into accumulator */ - if((file->cls->read)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0) - HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed") - - /* Copy into buffer */ - HDmemcpy(buf,file->meta_accum,size); - } /* end if */ - else { - /* Dispatch to driver */ - if((file->cls->read)(file, type, dxpl_id, addr, size, buf) < 0) - HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed") - } /* end else */ - } /* end else */ - } /* end if */ - else { - /* Dispatch to driver */ - if((file->cls->read)(file, type, dxpl_id, addr, size, buf) < 0) - HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed") - } /* end else */ + /* The real work */ + /* (Note compensating for base address addition in internal routine) */ + if(H5FD_write(file, dxpl_id, type, addr - file->base_addr, size, buf) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed") done: - FUNC_LEAVE_NOAPI(ret_value) -} + FUNC_LEAVE_API(ret_value) +} /* end H5FDwrite() */ /*------------------------------------------------------------------------- - * Function: H5FDwrite + * Function: H5FDflush * - * Purpose: Writes SIZE bytes to FILE beginning at address ADDR according - * to the data transfer property list DXPL_ID (which may be the - * constant H5P_DEFAULT). The bytes to be written come from the - * buffer BUF. + * Purpose: Notify driver to flush all cached data. If the driver has no + * flush method then nothing happens. * * Return: Success: Non-negative * @@ -2082,33 +1841,31 @@ done: * Thursday, July 29, 1999 * * Modifications: + * Quincey Koziol, May 20, 2002 + * Added 'closing' parameter * *------------------------------------------------------------------------- */ herr_t -H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, - const void *buf) +H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API(H5FDwrite, FAIL) - H5TRACE6("e", "*xMtiaz*x", file, type, dxpl_id, addr, size, buf); + FUNC_ENTER_API(H5FDflush, FAIL) + H5TRACE3("e", "*xiIu", file, dxpl_id, closing); /* Check args */ if(!file || !file->cls) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer") - /* Get the default dataset transfer property list if the user didn't provide one */ if(H5P_DEFAULT == dxpl_id) - dxpl_id= H5P_DATASET_XFER_DEFAULT; + dxpl_id = H5P_DATASET_XFER_DEFAULT; else - if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER)) + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list") - if(!buf) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null buffer") - /* The real work */ - if(H5FD_write(file, type, dxpl_id, addr, size, buf) < 0) - HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed") + /* Do the real work */ + if(H5FD_flush(file, dxpl_id, closing) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFLUSH, FAIL, "file flush request failed") done: FUNC_LEAVE_API(ret_value) @@ -2116,303 +1873,68 @@ done: /*------------------------------------------------------------------------- - * Function: H5FD_write + * Function: H5FD_flush * - * Purpose: Private version of H5FDwrite() + * Purpose: Private version of H5FDflush() * * Return: Success: Non-negative - * * Failure: Negative * * Programmer: Robb Matzke * Wednesday, August 4, 1999 * - * Modifications: - * Albert Cheng, 2000-11-21 - * Disable the code that does early return when size==0 for - * Parallel mode since a collective call would require the process - * to continue on with "nothing" to transfer. - * *------------------------------------------------------------------------- */ herr_t -H5FD_write(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, - const void *buf) +H5FD_flush(H5FD_t *file, hid_t dxpl_id, unsigned closing) { - size_t new_size; /* New size of the accumulator buffer */ - size_t old_offset; /* Offset of old data within the accumulator buffer */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_write, FAIL) - - assert(file && file->cls); - assert(H5I_GENPROP_LST==H5I_get_type(dxpl_id)); - assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - assert(buf); - -#ifndef H5_HAVE_PARALLEL - /* Do not return early for Parallel mode since the I/O could be a */ - /* collective transfer. */ - /* The no-op case */ - if(0==size) - HGOTO_DONE(SUCCEED) -#endif /* H5_HAVE_PARALLEL */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Check for accumulating metadata */ - if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && type!=H5FD_MEM_DRAW) { - /* Check if there is already metadata in the accumulator */ - if(file->accum_size>0) { - /* Check if the piece of metadata being written adjoins or is inside the metadata accumulator */ - if((addr>=file->accum_loc && addr<=(file->accum_loc+file->accum_size)) - || ((addr+size)>file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size)) - || (addr<file->accum_loc && (addr+size)>=file->accum_loc)) { - - /* Check if the new metadata adjoins the beginning of the current accumulator */ - if((addr+size)==file->accum_loc) { - /* Check if we need more buffer space */ - if((size+file->accum_size)>file->accum_buf_size) { - /* Adjust the buffer size, by doubling it */ - file->accum_buf_size = MAX(file->accum_buf_size*2,size+file->accum_size); - - /* Reallocate the metadata accumulator buffer */ - if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") -#ifdef H5_CLEAR_MEMORY -HDmemset(file->meta_accum + file->accum_size, 0, (file->accum_buf_size - (file->accum_size + size))); -#endif /* H5_CLEAR_MEMORY */ - } /* end if */ - - /* Move the existing metadata to the proper location */ - HDmemmove(file->meta_accum+size,file->meta_accum,file->accum_size); - - /* Copy the new metadata at the front */ - HDmemcpy(file->meta_accum,buf,size); - - /* Set the new size & location of the metadata accumulator */ - file->accum_loc=addr; - file->accum_size=file->accum_size+size; - - /* Mark it as written to */ - file->accum_dirty=TRUE; - } /* end if */ - /* Check if the new metadata adjoins the end of the current accumulator */ - else if(addr==(file->accum_loc+file->accum_size)) { - /* Check if we need more buffer space */ - if((size+file->accum_size)>file->accum_buf_size) { - /* Adjust the buffer size, by doubling it */ - file->accum_buf_size = MAX(file->accum_buf_size*2,size+file->accum_size); - - /* Reallocate the metadata accumulator buffer */ - if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") -#ifdef H5_CLEAR_MEMORY -HDmemset(file->meta_accum + file->accum_size + size, 0, (file->accum_buf_size - (file->accum_size + size))); -#endif /* H5_CLEAR_MEMORY */ - } /* end if */ - - /* Copy the new metadata to the end */ - HDmemcpy(file->meta_accum+file->accum_size,buf,size); - - /* Set the new size of the metadata accumulator */ - file->accum_size=file->accum_size+size; - - /* Mark it as written to */ - file->accum_dirty=TRUE; - } /* end if */ - /* Check if the new metadata is entirely within the current accumulator */ - else if(addr>=file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size)) { - /* Copy the new metadata to the proper location within the accumulator */ - HDmemcpy(file->meta_accum+(addr-file->accum_loc),buf,size); - - /* Mark it as written to */ - file->accum_dirty=TRUE; - } /* end if */ - /* Check if the new metadata overlaps the beginning of the current accumulator */ - else if(addr<file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size)) { - /* Calculate the new accumulator size, based on the amount of overlap */ - H5_ASSIGN_OVERFLOW(new_size,(file->accum_loc-addr)+file->accum_size,hsize_t,size_t); - - /* Check if we need more buffer space */ - if(new_size>file->accum_buf_size) { - /* Adjust the buffer size, by doubling it */ - file->accum_buf_size = MAX(file->accum_buf_size*2,new_size); - - /* Reallocate the metadata accumulator buffer */ - if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") -#ifdef H5_CLEAR_MEMORY -HDmemset(file->meta_accum + file->accum_size, 0, (file->accum_buf_size - file->accum_size)); -#endif /* H5_CLEAR_MEMORY */ - } /* end if */ - - /* Calculate the proper offset of the existing metadata */ - H5_ASSIGN_OVERFLOW(old_offset,(addr+size)-file->accum_loc,hsize_t,size_t); - - /* Move the existing metadata to the proper location */ - HDmemmove(file->meta_accum+size,file->meta_accum+old_offset,(file->accum_size-old_offset)); - - /* Copy the new metadata at the front */ - HDmemcpy(file->meta_accum,buf,size); - - /* Set the new size & location of the metadata accumulator */ - file->accum_loc=addr; - file->accum_size=new_size; - - /* Mark it as written to */ - file->accum_dirty=TRUE; - } /* end if */ - /* Check if the new metadata overlaps the end of the current accumulator */ - else if(addr>=file->accum_loc && (addr+size)>(file->accum_loc+file->accum_size)) { - /* Calculate the new accumulator size, based on the amount of overlap */ - H5_ASSIGN_OVERFLOW(new_size,(addr-file->accum_loc)+size,hsize_t,size_t); - - /* Check if we need more buffer space */ - if(new_size>file->accum_buf_size) { - /* Adjust the buffer size, by doubling it */ - file->accum_buf_size = MAX(file->accum_buf_size*2,new_size); - - /* Reallocate the metadata accumulator buffer */ - if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") -#ifdef H5_CLEAR_MEMORY -HDmemset(file->meta_accum + file->accum_size, 0, (file->accum_buf_size - file->accum_size)); -#endif /* H5_CLEAR_MEMORY */ - } /* end if */ - - /* Copy the new metadata to the end */ - HDmemcpy(file->meta_accum+(addr-file->accum_loc),buf,size); - - /* Set the new size & location of the metadata accumulator */ - file->accum_size=new_size; - - /* Mark it as written to */ - file->accum_dirty=TRUE; - } /* end if */ - else { - assert(0 && "New metadata overlapped both beginning and end of existing metadata accumulator!"); - } /* end else */ - } /* end if */ - /* New piece of metadata doesn't adjoin or overlap the existing accumulator */ - else { - /* Write out the existing metadata accumulator, with dispatch to driver */ - if(file->accum_dirty) { - if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0) - HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed") - /* Reset accumulator dirty flag */ - file->accum_dirty=FALSE; - } /* end if */ - - /* Cache the new piece of metadata */ - /* Check if we need to resize the buffer */ - if(size>file->accum_buf_size) { - /* Grow the metadata accumulator buffer */ - if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") - - /* Note the new buffer size */ - file->accum_buf_size=size; -#ifdef H5_CLEAR_MEMORY -{ -size_t clear_size = MAX(file->accum_size, size); -HDmemset(file->meta_accum + clear_size, 0, (file->accum_buf_size - clear_size)); -} -#endif /* H5_CLEAR_MEMORY */ - } /* end if */ - else { - /* Check if we should shrink the accumulator buffer */ - if(size<(file->accum_buf_size/H5FD_ACCUM_THROTTLE) && - file->accum_buf_size>H5FD_ACCUM_THRESHOLD) { - size_t tmp_size=(file->accum_buf_size/H5FD_ACCUM_THROTTLE); /* New size of accumulator buffer */ - - /* Shrink the accumulator buffer */ - if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,tmp_size))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") - - /* Note the new buffer size */ - file->accum_buf_size=tmp_size; - } /* end if */ - } /* end else */ - - /* Update the metadata accumulator information */ - file->accum_loc=addr; - file->accum_size=size; - file->accum_dirty=TRUE; - - /* Store the piece of metadata in the accumulator */ - HDmemcpy(file->meta_accum,buf,size); - } /* end else */ - } /* end if */ - /* No metadata in the accumulator, grab this piece and keep it */ - else { - /* Check if we need to reallocate the buffer */ - if(size>file->accum_buf_size) { - /* Reallocate the metadata accumulator buffer */ - if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") - - /* Note the new buffer size */ - file->accum_buf_size=size; - } /* end if */ + FUNC_ENTER_NOAPI(H5FD_flush, FAIL) - /* Update the metadata accumulator information */ - file->accum_loc=addr; - file->accum_size=size; - file->accum_dirty=TRUE; + HDassert(file && file->cls); - /* Store the piece of metadata in the accumulator */ - HDmemcpy(file->meta_accum,buf,size); - } /* end else */ - } /* end if */ - else { - /* Dispatch to driver */ - if((file->cls->write)(file, type, dxpl_id, addr, size, buf) < 0) - HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed") - } /* end else */ + if(file->cls->flush && (file->cls->flush)(file, dxpl_id, closing) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver flush request failed") done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_flush() */ /*------------------------------------------------------------------------- - * Function: H5FDflush + * Function: H5FDtruncate * - * Purpose: Notify driver to flush all cached data. If the driver has no - * flush method then nothing happens. + * Purpose: Notify driver to truncate the file back to the allocated size. * * Return: Success: Non-negative - * * Failure: Negative * - * Programmer: Robb Matzke - * Thursday, July 29, 1999 - * - * Modifications: - * Quincey Koziol, May 20, 2002 - * Added 'closing' parameter + * Programmer: Quincey Koziol + * Thursday, January 31, 2008 * *------------------------------------------------------------------------- */ herr_t -H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing) +H5FDtruncate(H5FD_t *file, hid_t dxpl_id, unsigned closing) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API(H5FDflush, FAIL) + FUNC_ENTER_API(H5FDtruncate, FAIL) H5TRACE3("e", "*xiIu", file, dxpl_id, closing); /* Check args */ if(!file || !file->cls) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer") if(H5P_DEFAULT == dxpl_id) - dxpl_id= H5P_DATASET_XFER_DEFAULT; + dxpl_id = H5P_DATASET_XFER_DEFAULT; else - if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER)) + if(TRUE != H5P_isa_class(dxpl_id,H5P_DATASET_XFER)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list") /* Do the real work */ - if(H5FD_flush(file,dxpl_id,closing) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "file flush request failed") + if(H5FD_truncate(file, dxpl_id, closing) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "file flush request failed") done: FUNC_LEAVE_API(ret_value) @@ -2420,49 +1942,33 @@ done: /*------------------------------------------------------------------------- - * Function: H5FD_flush + * Function: H5FD_truncate * - * Purpose: Private version of H5FDflush() + * Purpose: Private version of H5FDtruncate() * * Return: Success: Non-negative - * * Failure: Negative * - * Programmer: Robb Matzke - * Wednesday, August 4, 1999 - * - * Modifications: - * Quincey Koziol, May 20, 2002 - * Added 'closing' parameter + * Programmer: Quincey Koziol + * Thursday, January 31, 2008 * *------------------------------------------------------------------------- */ herr_t -H5FD_flush(H5FD_t *file, hid_t dxpl_id, unsigned closing) +H5FD_truncate(H5FD_t *file, hid_t dxpl_id, unsigned closing) { - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5FD_flush, FAIL) - - assert(file && file->cls); + herr_t ret_value = SUCCEED; /* Return value */ - /* Check if we need to flush out the metadata accumulator */ - if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && file->accum_dirty && file->accum_size>0) { - /* Flush the metadata contents */ - /* Not certain if the type and dxpl should be the way they are... -QAK */ - if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver write request failed") + FUNC_ENTER_NOAPI(H5FD_truncate, FAIL) - /* Reset the dirty flag */ - file->accum_dirty=FALSE; - } /* end if */ + HDassert(file && file->cls); - if(file->cls->flush && (file->cls->flush)(file,dxpl_id,closing) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver flush request failed") + if(file->cls->truncate && (file->cls->truncate)(file, dxpl_id, closing) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "driver truncate request failed") done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_truncate() */ /*------------------------------------------------------------------------- @@ -2563,3 +2069,33 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5FD_get_vfd_handle() */ + +/*-------------------------------------------------------------------------- + * Function: H5FD_set_base_addr + * + * Purpose: Set the base address for the file + * + * Return: Non-negative if succeed; negative if fails. + * + * Programmer: Quincey Koziol + * Jan. 17, 2008 + * + *-------------------------------------------------------------------------- + */ +herr_t +H5FD_set_base_addr(H5FD_t *file, haddr_t base_addr) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5FD_set_base_addr, FAIL) + + HDassert(file); + HDassert(H5F_addr_defined(base_addr)); + + /* Set the file's base address */ + file->base_addr = base_addr; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_set_base_addr() */ + diff --git a/src/H5FDcore.c b/src/H5FDcore.c index deef3ed..de49e9e 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -128,6 +128,7 @@ static const H5FD_class_t H5FD_core_g = { H5FD_core_read, /*read */ H5FD_core_write, /*write */ H5FD_core_flush, /*flush */ + NULL, /*truncate */ NULL, /*lock */ NULL, /*unlock */ H5FD_FLMAP_SINGLE /*fl_map */ @@ -898,3 +899,4 @@ H5FD_core_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) done: FUNC_LEAVE_NOAPI(ret_value) } + diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c index 980b16f..88a2af0 100644 --- a/src/H5FDdirect.c +++ b/src/H5FDdirect.c @@ -163,14 +163,14 @@ static herr_t H5FD_direct_close(H5FD_t *_file); static int H5FD_direct_cmp(const H5FD_t *_f1, const H5FD_t *_f2); static herr_t H5FD_direct_query(const H5FD_t *_f1, unsigned long *flags); static haddr_t H5FD_direct_get_eoa(const H5FD_t *_file, H5FD_mem_t type); -static herr_t H5FD_direct_set_eoa(H5FD_t *_file, H5FD_mem_t UNUSED type, haddr_t addr); +static herr_t H5FD_direct_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr); static haddr_t H5FD_direct_get_eof(const H5FD_t *_file); static herr_t H5FD_direct_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle); static herr_t H5FD_direct_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size, void *buf); static herr_t H5FD_direct_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size, const void *buf); -static herr_t H5FD_direct_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing); +static herr_t H5FD_direct_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); static const H5FD_class_t H5FD_direct_g = { "direct", /*name */ @@ -198,7 +198,8 @@ static const H5FD_class_t H5FD_direct_g = { H5FD_direct_get_handle, /*get_handle */ H5FD_direct_read, /*read */ H5FD_direct_write, /*write */ - H5FD_direct_flush, /*flush */ + NULL, /*flush */ + H5FD_direct_truncate, /*truncate */ NULL, /*lock */ NULL, /*unlock */ H5FD_FLMAP_SINGLE /*fl_map */ @@ -1238,7 +1239,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5FD_direct_flush + * Function: H5FD_direct_truncate * * Purpose: Makes sure that the true file size is the same (or larger) * than the end-of-address. @@ -1250,17 +1251,15 @@ done: * Programmer: Raymond Lu * Thursday, 21 September 2006 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t -H5FD_direct_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) +H5FD_direct_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing) { H5FD_direct_t *file = (H5FD_direct_t*)_file; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5FD_direct_flush, FAIL) + FUNC_ENTER_NOAPI(H5FD_direct_truncate, FAIL) assert(file); @@ -1301,5 +1300,6 @@ H5FD_direct_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_direct_truncate() */ #endif /* H5_HAVE_DIRECT */ + diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c index c70bfdb..5451cc0 100644 --- a/src/H5FDfamily.c +++ b/src/H5FDfamily.c @@ -107,6 +107,7 @@ static herr_t H5FD_family_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, ha static herr_t H5FD_family_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, const void *_buf); static herr_t H5FD_family_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing); +static herr_t H5FD_family_truncate(H5FD_t *_file, hid_t dxpl_id, unsigned closing); /* The class struct */ static const H5FD_class_t H5FD_family_g = { @@ -136,6 +137,7 @@ static const H5FD_class_t H5FD_family_g = { H5FD_family_read, /*read */ H5FD_family_write, /*write */ H5FD_family_flush, /*flush */ + H5FD_family_truncate, /*truncate */ NULL, /*lock */ NULL, /*unlock */ H5FD_FLMAP_SINGLE /*fl_map */ @@ -1051,13 +1053,13 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FD_family_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa) +H5FD_family_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t abs_eoa) { H5FD_family_t *file = (H5FD_family_t*)_file; - haddr_t addr=eoa; + haddr_t addr = abs_eoa; char memb_name[4096]; - unsigned u; /* Local index variable */ - herr_t ret_value=SUCCEED; /* Return value */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FD_family_set_eoa, FAIL) @@ -1076,32 +1078,34 @@ H5FD_family_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa) } /* end if */ /* Create another file if necessary */ - if (u>=file->nmembs || !file->memb[u]) { + if(u >= file->nmembs || !file->memb[u]) { file->nmembs = MAX(file->nmembs, u+1); sprintf(memb_name, file->name, u); H5E_BEGIN_TRY { - H5_CHECK_OVERFLOW(file->memb_size,hsize_t,haddr_t); - file->memb[u] = H5FDopen(memb_name, file->flags|H5F_ACC_CREAT, + H5_CHECK_OVERFLOW(file->memb_size, hsize_t, haddr_t); + file->memb[u] = H5FDopen(memb_name, file->flags | H5F_ACC_CREAT, file->memb_fapl_id, (haddr_t)file->memb_size); } H5E_END_TRY; - if (NULL==file->memb[u]) + if(NULL == file->memb[u]) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to open member file") - } + } /* end if */ /* Set the EOA marker for the member */ - H5_CHECK_OVERFLOW(file->memb_size,hsize_t,haddr_t); - if (addr>(haddr_t)file->memb_size) { - if(H5FD_set_eoa(file->memb[u], type, (haddr_t)file->memb_size)<0) + /* (Note compensating for base address addition in internal routine) */ + H5_CHECK_OVERFLOW(file->memb_size, hsize_t, haddr_t); + if(addr > (haddr_t)file->memb_size) { + if(H5FD_set_eoa(file->memb[u], type, ((haddr_t)file->memb_size - file->pub.base_addr)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set file eoa") addr -= file->memb_size; - } else { - if(H5FD_set_eoa(file->memb[u], type, addr)<0) + } /* end if */ + else { + if(H5FD_set_eoa(file->memb[u], type, (addr - file->pub.base_addr)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set file eoa") addr = 0; - } - } + } /* end else */ + } /* end for */ - file->eoa = eoa; + file->eoa = abs_eoa; done: FUNC_LEAVE_NOAPI(ret_value) @@ -1142,13 +1146,16 @@ H5FD_family_get_eof(const H5FD_t *_file) * with `i' equal to that member. If all members have zero EOF then exit * loop with i==0. */ - assert(file->nmembs>0); - for (i=(int)file->nmembs-1; i>=0; --i) { - if ((eof=H5FD_get_eof(file->memb[i]))!=0) + HDassert(file->nmembs > 0); + for(i = (int)file->nmembs - 1; i >= 0; --i) { + if((eof = H5FD_get_eof(file->memb[i])) != 0) break; - if (0==i) + if(0 == i) break; - } + } /* end for */ + + /* Adjust for base address for file */ + eof += file->pub.base_addr; /* * The file size is the number of members before the i'th member plus the @@ -1157,7 +1164,7 @@ H5FD_family_get_eof(const H5FD_t *_file) eof += ((unsigned)i)*file->memb_size; /* Set return value */ - ret_value=MAX(eof, file->eoa); + ret_value = MAX(eof, file->eoa); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1396,3 +1403,39 @@ H5FD_family_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing) done: FUNC_LEAVE_NOAPI(ret_value) } + + +/*------------------------------------------------------------------------- + * Function: H5FD_family_truncate + * + * Purpose: Truncates all family members. + * + * Return: Success: 0 + * + * Failure: -1, as many files truncated as possible. + * + * Programmer: Quincey Koziol + * Saturday, February 23, 2008 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_family_truncate(H5FD_t *_file, hid_t dxpl_id, unsigned closing) +{ + H5FD_family_t *file = (H5FD_family_t*)_file; + unsigned u, nerrors = 0; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_family_truncate, FAIL) + + for(u = 0; u < file->nmembs; u++) + if(file->memb[u] && H5FD_truncate(file->memb[u], dxpl_id, closing) < 0) + nerrors++; + + if(nerrors) + HGOTO_ERROR(H5E_IO, H5E_BADVALUE, FAIL, "unable to flush member files") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_family_truncate() */ + diff --git a/src/H5FDint.c b/src/H5FDint.c new file mode 100644 index 0000000..aa375e2 --- /dev/null +++ b/src/H5FDint.c @@ -0,0 +1,297 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5FDint.c + * Jan 17 2008 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: Internal routine for VFD operations + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5FD_PACKAGE /*suppress error about including H5FDpkg */ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5FD_int_init_interface + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fprivate.h" /* File access */ +#include "H5FDpkg.h" /* File Drivers */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Pprivate.h" /* Property lists */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*-------------------------------------------------------------------------- +NAME + H5FD_int_init_interface -- Initialize interface-specific information +USAGE + herr_t H5FD_int_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_int_init_interface(void) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_int_init_interface) + + FUNC_LEAVE_NOAPI(H5FD_init()) +} /* H5FD_int_init_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_read + * + * Purpose: Private version of H5FDread() + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Robb Matzke + * Wednesday, August 4, 1999 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_read(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, + size_t size, void *buf/*out*/) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_read, FAIL) + + HDassert(file && file->cls); + HDassert(H5I_GENPROP_LST == H5I_get_type(dxpl_id)); + HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER)); + HDassert(buf); + +#ifndef H5_HAVE_PARALLEL + /* Do not return early for Parallel mode since the I/O could be a */ + /* collective transfer. */ + /* The no-op case */ + if(0 == size) + HGOTO_DONE(SUCCEED) +#endif /* H5_HAVE_PARALLEL */ + + /* Dispatch to driver */ + if((file->cls->read)(file, type, dxpl_id, addr + file->base_addr, size, buf) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_write + * + * Purpose: Private version of H5FDwrite() + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Robb Matzke + * Wednesday, August 4, 1999 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_write(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, + size_t size, const void *buf) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_write, FAIL) + + HDassert(file && file->cls); + HDassert(H5I_GENPROP_LST == H5I_get_type(dxpl_id)); + HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER)); + HDassert(buf); + +#ifndef H5_HAVE_PARALLEL + /* Do not return early for Parallel mode since the I/O could be a */ + /* collective transfer. */ + /* The no-op case */ + if(0 == size) + HGOTO_DONE(SUCCEED) +#endif /* H5_HAVE_PARALLEL */ + + /* Dispatch to driver */ + if((file->cls->write)(file, type, dxpl_id, addr + file->base_addr, size, buf) < 0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_write() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_set_eoa + * + * Purpose: Private version of H5FDset_eoa() + * + * Return: Success: Non-negative + * Failure: Negative, no side effect + * + * Programmer: Robb Matzke + * Wednesday, August 4, 1999 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_set_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_set_eoa, FAIL) + + HDassert(file && file->cls); + HDassert(H5F_addr_defined(addr) && addr <= file->maxaddr); + + /* Dispatch to driver */ + if((file->cls->set_eoa)(file, type, addr + file->base_addr) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver set_eoa request failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_set_eoa() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_get_eoa + * + * Purpose: Private version of H5FDget_eoa() + * + * Return: Success: First byte after allocated memory. + * Failure: HADDR_UNDEF + * + * Programmer: Robb Matzke + * Wednesday, August 4, 1999 + * + *------------------------------------------------------------------------- + */ +haddr_t +H5FD_get_eoa(const H5FD_t *file, H5FD_mem_t type) +{ + haddr_t ret_value; + + FUNC_ENTER_NOAPI(H5FD_get_eoa, HADDR_UNDEF) + + HDassert(file && file->cls); + + /* Dispatch to driver */ + if(HADDR_UNDEF == (ret_value = (file->cls->get_eoa)(file, type))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed") + + /* Adjust for base address in file */ + ret_value -= file->base_addr; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_get_eoa() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_get_eof + * + * Purpose: Private version of H5FDget_eof() + * + * Return: Success: The EOF address. + * + * Failure: HADDR_UNDEF + * + * Programmer: Robb Matzke + * Wednesday, August 4, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +haddr_t +H5FD_get_eof(const H5FD_t *file) +{ + haddr_t ret_value; + + FUNC_ENTER_NOAPI(H5FD_get_eof, HADDR_UNDEF) + + HDassert(file && file->cls); + + /* Dispatch to driver */ + if(file->cls->get_eof) { + if(HADDR_UNDEF == (ret_value = (file->cls->get_eof)(file))) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eof request failed") + } /* end if */ + else + ret_value = file->maxaddr; + + /* Adjust for base address in file */ + ret_value -= file->base_addr; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_get_eof() */ + diff --git a/src/H5FDlog.c b/src/H5FDlog.c index 9a34a45..2a4dae6 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -190,7 +190,7 @@ static herr_t H5FD_log_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr size_t size, void *buf); static herr_t H5FD_log_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size, const void *buf); -static herr_t H5FD_log_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing); +static herr_t H5FD_log_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); #ifdef OLD_WAY /* @@ -233,14 +233,11 @@ static const H5FD_class_t H5FD_log_g = { H5FD_log_get_handle, /*get_handle */ H5FD_log_read, /*read */ H5FD_log_write, /*write */ - H5FD_log_flush, /*flush */ + NULL, /*flush */ + H5FD_log_truncate, /*truncate */ NULL, /*lock */ NULL, /*unlock */ -#ifdef OLD_WAY - H5FD_FLMAP_NOLIST /*fl_map */ -#else /* OLD_WAY */ H5FD_FLMAP_SINGLE /*fl_map */ -#endif /* OLD_WAY */ }; @@ -1306,30 +1303,27 @@ done: /*------------------------------------------------------------------------- - * Function: H5FD_log_flush + * Function: H5FD_log_truncate * * Purpose: Makes sure that the true file size is the same (or larger) * than the end-of-address. * * Return: Success: Non-negative - * * Failure: Negative * * Programmer: Robb Matzke * Wednesday, August 4, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ /* ARGSUSED */ static herr_t -H5FD_log_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) +H5FD_log_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) { H5FD_log_t *file = (H5FD_log_t*)_file; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5FD_log_flush, FAIL) + FUNC_ENTER_NOAPI(H5FD_log_truncate, FAIL) if(file->eoa>file->eof) { if(-1 == file_seek(file->fd, (file_offset_t)(file->eoa - 1), SEEK_SET)) @@ -1343,4 +1337,5 @@ H5FD_log_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_log_truncate() */ + diff --git a/src/H5FDmpi.h b/src/H5FDmpi.h index 885e844..b9998dd 100644 --- a/src/H5FDmpi.h +++ b/src/H5FDmpi.h @@ -120,3 +120,4 @@ H5_DLL MPI_Comm H5FD_mpi_get_comm(const H5FD_t *_file); #endif /* H5_HAVE_PARALLEL */ #endif /* H5FDmpi_H */ + diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index 2bc0754..ea5a768 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -82,6 +82,7 @@ static herr_t H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hadd static herr_t H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, const void *buf); static herr_t H5FD_mpio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing); +static herr_t H5FD_mpio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); static int H5FD_mpio_mpi_rank(const H5FD_t *_file); static int H5FD_mpio_mpi_size(const H5FD_t *_file); static MPI_Comm H5FD_mpio_communicator(const H5FD_t *_file); @@ -121,6 +122,7 @@ static const H5FD_class_mpi_t H5FD_mpio_g = { H5FD_mpio_read, /*read */ H5FD_mpio_write, /*write */ H5FD_mpio_flush, /*flush */ + H5FD_mpio_truncate, /*truncate */ NULL, /*lock */ NULL, /*unlock */ H5FD_FLMAP_SINGLE /*fl_map */ @@ -1859,68 +1861,106 @@ done: * * Failure: Negative * - * Programmer: Unknown + * Programmer: Robb Matzke * January 30, 1998 * - * Modifications: - * Robb Matzke, 1998-02-18 - * Added the ACCESS_PARMS argument. + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_mpio_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing) +{ + H5FD_mpio_t *file = (H5FD_mpio_t*)_file; + int mpi_code; /* mpi return code */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5FD_mpio_flush, FAIL) + +#ifdef H5FDmpio_DEBUG + if(H5FD_mpio_Debug[(int)'t']) + HDfprintf(stdout, "Entering %s\n", FUNC); +#endif + HDassert(file); + HDassert(H5FD_MPIO == file->pub.driver_id); + + /* Only sync the file if we are not going to immediately close it */ + if(!closing) { + if(MPI_SUCCESS != (mpi_code = MPI_File_sync(file->f))) + HMPI_GOTO_ERROR(FAIL, "MPI_File_sync failed", mpi_code) + } /* end if */ + +done: +#ifdef H5FDmpio_DEBUG + if(H5FD_mpio_Debug[(int)'t']) + HDfprintf(stdout, "Leaving %s\n", FUNC); +#endif + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_mpio_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_mpio_truncate * - * Robb Matzke, 1999-08-06 - * Modified to work with the virtual file layer. + * Purpose: Make certain the file's size matches it's allocated size * - * Robb Matzke, 2000-12-29 - * Make sure file size is at least as large as the last - * allocated byte. + * Return: Success: Non-negative + * Failure: Negative * - * Quincey Koziol, 2002-06-?? - * Changed file extension method to use MPI_File_set_size instead - * read->write method. + * Programmer: Quincey Koziol + * January 31, 2008 * *------------------------------------------------------------------------- */ static herr_t -H5FD_mpio_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing) +H5FD_mpio_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing) { H5FD_mpio_t *file = (H5FD_mpio_t*)_file; - int mpi_code; /* mpi return code */ - MPI_Offset mpi_off; - herr_t ret_value=SUCCEED; + herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(H5FD_mpio_flush, FAIL) + FUNC_ENTER_NOAPI(H5FD_mpio_truncate, FAIL) #ifdef H5FDmpio_DEBUG - if (H5FD_mpio_Debug[(int)'t']) - fprintf(stdout, "Entering H5FD_mpio_flush\n" ); + if(H5FD_mpio_Debug[(int)'t']) + HDfprintf(stdout, "Entering %s\n", FUNC); #endif - assert(file); - assert(H5FD_MPIO==file->pub.driver_id); + HDassert(file); + HDassert(H5FD_MPIO == file->pub.driver_id); /* Extend the file to make sure it's large enough, then sync. * Unfortunately, keeping track of EOF is an expensive operation, so * we can't just check whether EOF<EOA like with other drivers. * Therefore we'll just read the byte at EOA-1 and then write it back. */ - if(file->eoa>file->last_eoa) { + if(file->eoa > file->last_eoa) { + int mpi_code; /* mpi return code */ + MPI_Offset mpi_off; + #ifdef H5_MPI_FILE_SET_SIZE_BIG - if (H5FD_mpi_haddr_to_MPIOff(file->eoa, &mpi_off)<0) + if(H5FD_mpi_haddr_to_MPIOff(file->eoa, &mpi_off) < 0) HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "cannot convert from haddr_t to MPI_Offset") /* Extend the file's size */ - if (MPI_SUCCESS != (mpi_code=MPI_File_set_size(file->f, mpi_off))) + if(MPI_SUCCESS != (mpi_code = MPI_File_set_size(file->f, mpi_off))) HMPI_GOTO_ERROR(FAIL, "MPI_File_set_size failed", mpi_code) #else /* H5_MPI_FILE_SET_SIZE_BIG */ - if (0==file->mpi_rank) { - uint8_t byte=0; + /* Wait until all processes are here before reading/writing the byte at + * process 0's end of address space. The window for corruption is + * probably tiny, but does exist... + */ + if(MPI_SUCCESS != (mpi_code = MPI_Barrier(file->comm))) + HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code) + + if(0 == file->mpi_rank) { + uint8_t byte = 0; MPI_Status mpi_stat; /* Portably initialize MPI status variable */ - HDmemset(&mpi_stat,0,sizeof(MPI_Status)); + HDmemset(&mpi_stat, 0, sizeof(MPI_Status)); - if (H5FD_mpi_haddr_to_MPIOff(file->eoa-1, &mpi_off)<0) + if(H5FD_mpi_haddr_to_MPIOff(file->eoa-1, &mpi_off) < 0) HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "cannot convert from haddr_t to MPI_Offset") - if (MPI_SUCCESS != (mpi_code=MPI_File_read_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat))) + if(MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat))) HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code) - if (MPI_SUCCESS != (mpi_code=MPI_File_write_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat))) + if(MPI_SUCCESS != (mpi_code = MPI_File_write_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat))) HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code) } /* end if */ #endif /* H5_MPI_FILE_SET_SIZE_BIG */ @@ -1931,27 +1971,21 @@ H5FD_mpio_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing) * it the shorter length, potentially truncating the file and dropping * the new data written) */ - if (MPI_SUCCESS!= (mpi_code=MPI_Barrier(file->comm))) + if(MPI_SUCCESS != (mpi_code = MPI_Barrier(file->comm))) HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code) /* Update the 'last' eoa value */ - file->last_eoa=file->eoa; - } /* end if */ - - /* Only sync the file if we are not going to immediately close it */ - if(!closing) { - if (MPI_SUCCESS != (mpi_code=MPI_File_sync(file->f))) - HMPI_GOTO_ERROR(FAIL, "MPI_File_sync failed", mpi_code) + file->last_eoa = file->eoa; } /* end if */ done: #ifdef H5FDmpio_DEBUG - if (H5FD_mpio_Debug[(int)'t']) - fprintf(stdout, "Leaving H5FD_mpio_flush\n" ); + if(H5FD_mpio_Debug[(int)'t']) + HDfprintf(stdout, "Leaving %s\n", FUNC); #endif FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_mpio_truncate() */ /*------------------------------------------------------------------------- diff --git a/src/H5FDmpio.h b/src/H5FDmpio.h index 8fa1be5..41baf8d 100644 --- a/src/H5FDmpio.h +++ b/src/H5FDmpio.h @@ -31,7 +31,7 @@ /* Macros */ #define IS_H5FD_MPIO(f) /* (H5F_t *f) */ \ - (H5FD_MPIO==H5F_get_driver_id(f)) + (H5FD_MPIO==H5F_DRIVER_ID(f)) #ifdef H5_HAVE_PARALLEL /*Turn on H5FDmpio_debug if H5F_DEBUG is on */ diff --git a/src/H5FDmpiposix.c b/src/H5FDmpiposix.c index 9683e27..03e8cb3 100644 --- a/src/H5FDmpiposix.c +++ b/src/H5FDmpiposix.c @@ -190,7 +190,7 @@ static herr_t H5FD_mpiposix_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, size_t size, void *buf); static herr_t H5FD_mpiposix_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size, const void *buf); -static herr_t H5FD_mpiposix_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing); +static herr_t H5FD_mpiposix_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); static int H5FD_mpiposix_mpi_rank(const H5FD_t *_file); static int H5FD_mpiposix_mpi_size(const H5FD_t *_file); static MPI_Comm H5FD_mpiposix_communicator(const H5FD_t *_file); @@ -229,7 +229,8 @@ static const H5FD_class_mpi_t H5FD_mpiposix_g = { H5FD_mpiposix_get_handle, /*get_handle */ H5FD_mpiposix_read, /*read */ H5FD_mpiposix_write, /*write */ - H5FD_mpiposix_flush, /*flush */ + NULL, /*flush */ + H5FD_mpiposix_truncate, /*truncate */ NULL, /*lock */ NULL, /*unlock */ H5FD_FLMAP_SINGLE /*fl_map */ @@ -1365,9 +1366,10 @@ done: /*------------------------------------------------------------------------- - * Function: H5FD_mpiposix_flush + * Function: H5FD_mpiposix_truncate * - * Purpose: Makes sure that all data is on disk. This is collective. + * Purpose: Makes sure that the true file size is the same (or larger) + * than the end-of-address. * * Return: Success: Non-negative * Failure: Negative @@ -1375,12 +1377,10 @@ done: * Programmer: Quincey Koziol * Thursday, July 11, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t -H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) +H5FD_mpiposix_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing) { H5FD_mpiposix_t *file = (H5FD_mpiposix_t*)_file; #ifdef _WIN32 @@ -1388,15 +1388,15 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */ #endif /* _WIN32 */ int mpi_code; /* MPI return code */ - herr_t ret_value=SUCCEED; + herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(H5FD_mpiposix_flush, FAIL) + FUNC_ENTER_NOAPI(H5FD_mpiposix_truncate, FAIL) - assert(file); - assert(H5FD_MPIPOSIX==file->pub.driver_id); + HDassert(file); + HDassert(H5FD_MPIPOSIX == file->pub.driver_id); /* Extend the file to make sure it's large enough */ - if(file->eoa>file->last_eoa) { + if(file->eoa > file->last_eoa) { /* Use the round-robin process to truncate (extend) the file */ if(file->mpi_rank == H5_PAR_META_WRITE) { #ifdef _WIN32 @@ -1406,8 +1406,8 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing /* Translate 64-bit integers into form Windows wants */ /* [This algorithm is from the Windows documentation for SetFilePointer()] */ li.QuadPart = file->eoa; - SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN); - if(SetEndOfFile((HANDLE)filehandle)==0) + SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN); + if(SetEndOfFile((HANDLE)filehandle) == 0) HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") #else /* _WIN32 */ if(-1==file_truncate(file->fd, (file_offset_t)file->eoa)) @@ -1421,11 +1421,11 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing * it the shorter length, potentially truncating the file and dropping * the new data written) */ - if (MPI_SUCCESS!= (mpi_code=MPI_Barrier(file->comm))) + if(MPI_SUCCESS != (mpi_code = MPI_Barrier(file->comm))) HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code) /* Update the 'last' eoa and eof values */ - file->last_eoa=file->eoa; + file->last_eoa = file->eoa; file->eof = file->eoa; /* Reset last file I/O information */ @@ -1435,7 +1435,7 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_mpiposix_flush() */ +} /* end H5FD_mpiposix_truncate() */ /*------------------------------------------------------------------------- diff --git a/src/H5FDmpiposix.h b/src/H5FDmpiposix.h index 70e632a..832839e 100644 --- a/src/H5FDmpiposix.h +++ b/src/H5FDmpiposix.h @@ -32,7 +32,7 @@ /* Macros */ #define IS_H5FD_MPIPOSIX(f) /* (H5F_t *f) */ \ - (H5FD_MPIPOSIX==H5F_get_driver_id(f)) + (H5FD_MPIPOSIX==H5F_DRIVER_ID(f)) #ifdef H5_HAVE_PARALLEL @@ -54,4 +54,3 @@ H5_DLL herr_t H5Pget_fapl_mpiposix(hid_t fapl_id, MPI_Comm *comm/*out*/, hbool_t #endif /* __H5FDmpiposix_H */ - diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c index 27a7cac..6b53d9e 100644 --- a/src/H5FDmulti.c +++ b/src/H5FDmulti.c @@ -152,6 +152,7 @@ static herr_t H5FD_multi_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, had static herr_t H5FD_multi_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, const void *_buf); static herr_t H5FD_multi_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing); +static herr_t H5FD_multi_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); /* The class struct */ static const H5FD_class_t H5FD_multi_g = { @@ -181,6 +182,7 @@ static const H5FD_class_t H5FD_multi_g = { H5FD_multi_read, /*read */ H5FD_multi_write, /*write */ H5FD_multi_flush, /*flush */ + H5FD_multi_truncate, /*truncate */ NULL, /*lock */ NULL, /*unlock */ H5FD_FLMAP_DEFAULT /*fl_map */ @@ -1461,7 +1463,7 @@ H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type) const H5FD_multi_t *file = (const H5FD_multi_t*)_file; haddr_t eoa = 0; haddr_t memb_eoa = 0; - static const char *func="H5FD_multi_eof"; /* Function Name for error reporting */ + static const char *func="H5FD_multi_eoa"; /* Function Name for error reporting */ /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); @@ -1470,7 +1472,7 @@ H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type) * taken out because it makes little sense for MULTI files. * However, the library sometimes queries it through H5F_get_eoa. * Here the code finds the biggest EOA for individual file if - * the query is from H5F_get_eoa (TYPE is H5FD_MEM_DEFAULT). + * the query is for TYPE == H5FD_MEM_DEFAULT. */ if(H5FD_MEM_DEFAULT == type) { UNIQUE_MEMBERS(file->fa.memb_map, mt) { @@ -1507,6 +1509,7 @@ H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type) if (HADDR_UNDEF==eoa) H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eoa", HADDR_UNDEF) + if (eoa>0) eoa += file->fa.memb_addr[mmt]; } else if (file->fa.relax) { /* * The member is not open yet (maybe it doesn't exist). Make the @@ -1551,14 +1554,22 @@ static herr_t H5FD_multi_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa) { H5FD_multi_t *file = (H5FD_multi_t*)_file; + H5FD_mem_t mmt; herr_t status; static const char *func="H5FD_multi_set_eoa"; /* Function Name for error reporting */ /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); + mmt = file->fa.memb_map[type]; + if(H5FD_MEM_DEFAULT == mmt) + mmt = type; + + assert(eoa >= file->fa.memb_addr[mmt]); + assert(eoa < file->memb_next[mmt]); + H5E_BEGIN_TRY { - status = H5FDset_eoa(file->memb[type], type, eoa); + status = H5FDset_eoa(file->memb[mmt], mmt, (eoa - file->fa.memb_addr[mmt])); } H5E_END_TRY; if (status<0) H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_BADVALUE, "member H5FDset_eoa failed", -1) @@ -1596,7 +1607,7 @@ H5FD_multi_get_eof(const H5FD_t *_file) const H5FD_multi_t *file = (const H5FD_multi_t*)_file; haddr_t eof=0, tmp_eof; haddr_t eoa=0, tmp_eoa; - static const char *func="H5FD_multi_eof"; /* Function Name for error reporting */ + static const char *func="H5FD_multi_get_eof"; /* Function Name for error reporting */ /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); @@ -1619,6 +1630,7 @@ H5FD_multi_get_eof(const H5FD_t *_file) if (HADDR_UNDEF==tmp_eoa) H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eoa", HADDR_UNDEF) + if (tmp_eoa>0) tmp_eoa += file->fa.memb_addr[mt]; } else if (file->fa.relax) { /* * The member is not open yet (maybe it doesn't exist). Make the @@ -1701,7 +1713,7 @@ H5FD_multi_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) mmt = file->fa.memb_map[type]; if (H5FD_MEM_DEFAULT==mmt) mmt = type; - if (HADDR_UNDEF==(addr=H5FDalloc(file->memb[mmt], type, dxpl_id, size))) + if (HADDR_UNDEF==(addr=H5FDalloc(file->memb[mmt], mmt, dxpl_id, size))) H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file can't alloc", HADDR_UNDEF) addr += file->fa.memb_addr[mmt]; @@ -1753,7 +1765,7 @@ H5FD_multi_free(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsi assert(addr>=file->fa.memb_addr[mmt]); assert(addr+size<=file->memb_next[mmt]); - return H5FDfree(file->memb[mmt], type, dxpl_id, addr-file->fa.memb_addr[mmt], size); + return H5FDfree(file->memb[mmt], mmt, dxpl_id, addr-file->fa.memb_addr[mmt], size); } @@ -1943,6 +1955,46 @@ H5FD_multi_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing) /*------------------------------------------------------------------------- + * Function: H5FD_multi_truncate + * + * Purpose: Truncates all multi members. + * + * Return: Success: 0 + * Failure: -1, as many files truncated as possible. + * + * Programmer: Quincey Koziol + * Thursday, January 31, 2008 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_multi_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing) +{ + H5FD_multi_t *file = (H5FD_multi_t*)_file; + H5FD_mem_t mt; + int nerrors=0; + static const char *func="H5FD_multi_truncate"; /* Function Name for error reporting */ + + /* Clear the error stack */ + H5Eclear2(H5E_DEFAULT); + + /* Truncate each file */ + for(mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) { + if(file->memb[mt]) { + H5E_BEGIN_TRY { + if(H5FDtruncate(file->memb[mt], dxpl_id, closing) < 0) + nerrors++; + } H5E_END_TRY; + } + } + if(nerrors) + H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error truncating member files", -1) + + return 0; +} /* end H5FD_multi_truncate() */ + + +/*------------------------------------------------------------------------- * Function: compute_next * * Purpose: Compute the memb_next[] values of the file based on the diff --git a/src/H5FDpkg.h b/src/H5FDpkg.h index 700ec1d..9401b52 100644 --- a/src/H5FDpkg.h +++ b/src/H5FDpkg.h @@ -48,15 +48,11 @@ /* 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 */ diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h index f4797bb..25b2f24 100644 --- a/src/H5FDprivate.h +++ b/src/H5FDprivate.h @@ -55,27 +55,25 @@ H5_DLL H5FD_t *H5FD_open(const char *name, unsigned flags, hid_t fapl_id, H5_DLL herr_t H5FD_close(H5FD_t *file); H5_DLL int H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2); H5_DLL int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/); -H5_DLL haddr_t H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); -H5_DLL herr_t H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size); -H5_DLL 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); +H5_DLL haddr_t H5FD_alloc(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, hsize_t size, haddr_t *align_addr, hsize_t *align_size); +H5_DLL herr_t H5FD_free(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, hsize_t size); +H5_DLL htri_t H5FD_try_extend(H5FD_t *file, H5FD_mem_t type, haddr_t blk_end, + hsize_t extra_requested); 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, - const void *buf); +H5_DLL herr_t H5FD_get_feature_flags(const H5FD_t *file, unsigned long *feature_flags); +H5_DLL herr_t H5FD_get_fs_type_map(const H5FD_t *file, H5FD_mem_t *type_map); +H5_DLL herr_t H5FD_read(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, + haddr_t addr, size_t size, void *buf/*out*/); +H5_DLL herr_t H5FD_write(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, + haddr_t addr, size_t size, const void *buf); H5_DLL herr_t H5FD_flush(H5FD_t *file, hid_t dxpl_id, unsigned closing); +H5_DLL herr_t H5FD_truncate(H5FD_t *file, hid_t dxpl_id, hbool_t closing); H5_DLL herr_t H5FD_get_fileno(const H5FD_t *file, unsigned long *filenum); H5_DLL herr_t H5FD_get_vfd_handle(H5FD_t *file, hid_t fapl, void** file_handle); -H5_DLL hssize_t H5FD_get_freespace(const H5FD_t *file); -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); +H5_DLL herr_t H5FD_set_base_addr(H5FD_t *file, haddr_t base_addr); #endif /* !_H5FDprivate_H */ diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index ea92649..85d316d 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -210,6 +210,7 @@ typedef struct H5FD_class_t { herr_t (*write)(H5FD_t *file, H5FD_mem_t type, hid_t dxpl, haddr_t addr, size_t size, const void *buffer); herr_t (*flush)(H5FD_t *file, hid_t dxpl_id, unsigned closing); + herr_t (*truncate)(H5FD_t *file, hid_t dxpl_id, hbool_t closing); herr_t (*lock)(H5FD_t *file, unsigned char *oid, unsigned lock_type, hbool_t last); herr_t (*unlock)(H5FD_t *file, unsigned char *oid, hbool_t last); H5FD_mem_t fl_map[H5FD_MEM_NTYPES]; @@ -222,15 +223,6 @@ 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. @@ -238,32 +230,14 @@ typedef struct H5FD_blk_aggr_t { struct H5FD_t { hid_t driver_id; /*driver ID for this file */ const H5FD_class_t *cls; /*constant class info */ - unsigned long fileno; /* File serial number */ + unsigned long fileno; /* File 'serial' number */ unsigned long feature_flags; /* VFL Driver feature Flags */ + haddr_t maxaddr; /* For this file, overrides class */ + haddr_t base_addr; /* Base address for HDF5 data w/in file */ + + /* Space allocation management fields */ hsize_t threshold; /* Threshold for alignment */ hsize_t alignment; /* Allocation alignment */ - - /* 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 */ - haddr_t accum_loc; /* File location (offset) of the - * accumulated metadata */ - size_t accum_size; /* Size of the accumulated - * metadata buffer used (in - * bytes) */ - size_t accum_buf_size; /* Size of the accumulated - * metadata buffer allocated (in - * bytes) */ - unsigned accum_dirty; /* Flag to indicate that the - * accumulated metadata is dirty */ - haddr_t maxaddr; /* For this file, overrides class */ - H5FD_free_t *fl[H5FD_MEM_NTYPES]; /* Freelist per allocation type */ - hsize_t maxsize; /* Largest object on FL, or zero */ }; #ifdef __cplusplus @@ -281,8 +255,6 @@ H5_DLL int H5FDquery(const H5FD_t *f, unsigned long *flags); H5_DLL haddr_t H5FDalloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); H5_DLL herr_t H5FDfree(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size); -H5_DLL haddr_t H5FDrealloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, - haddr_t addr, hsize_t old_size, hsize_t new_size); H5_DLL haddr_t H5FDget_eoa(H5FD_t *file, H5FD_mem_t type); H5_DLL herr_t H5FDset_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t eoa); H5_DLL haddr_t H5FDget_eof(H5FD_t *file); @@ -292,6 +264,7 @@ H5_DLL herr_t H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, H5_DLL herr_t H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, const void *buf); H5_DLL herr_t H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing); +H5_DLL herr_t H5FDtruncate(H5FD_t *file, hid_t dxpl_id, hbool_t closing); #ifdef __cplusplus } diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c index 1073a87..cace117 100644 --- a/src/H5FDsec2.c +++ b/src/H5FDsec2.c @@ -158,7 +158,7 @@ static herr_t H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, hadd size_t size, void *buf); static herr_t H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size, const void *buf); -static herr_t H5FD_sec2_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing); +static herr_t H5FD_sec2_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); static const H5FD_class_t H5FD_sec2_g = { "sec2", /*name */ @@ -186,7 +186,8 @@ static const H5FD_class_t H5FD_sec2_g = { H5FD_sec2_get_handle, /*get_handle */ H5FD_sec2_read, /*read */ H5FD_sec2_write, /*write */ - H5FD_sec2_flush, /*flush */ + NULL, /*flush */ + H5FD_sec2_truncate, /*truncate */ NULL, /*lock */ NULL, /*unlock */ H5FD_FLMAP_SINGLE /*fl_map */ @@ -419,22 +420,28 @@ done: * Programmer: Robb Matzke * Thursday, July 29, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t H5FD_sec2_close(H5FD_t *_file) { H5FD_sec2_t *file = (H5FD_sec2_t*)_file; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FD_sec2_close, FAIL) +#ifdef QAK +HDfprintf(stderr, "%s: file->eof = %a, file->eoa = %a\n", FUNC, file->eof, file->eoa); +#endif /* QAK */ + + /* Sanity check */ + HDassert(file); - if (HDclose(file->fd)<0) + /* Close the underlying file */ + if(HDclose(file->fd) < 0) HSYS_GOTO_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file") - (void)H5FL_FREE(H5FD_sec2_t,file); + /* Release the file info */ + (void)H5FL_FREE(H5FD_sec2_t, file); done: FUNC_LEAVE_NOAPI(ret_value) @@ -612,7 +619,7 @@ H5FD_sec2_set_eoa(H5FD_t *_file, H5FD_mem_t UNUSED type, haddr_t addr) done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_sec2_set_eoa() */ /*------------------------------------------------------------------------- @@ -765,7 +772,7 @@ done: } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_sec2_read() */ /*------------------------------------------------------------------------- @@ -846,11 +853,11 @@ done: } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_sec2_write() */ /*------------------------------------------------------------------------- - * Function: H5FD_sec2_flush + * Function: H5FD_sec2_truncate * * Purpose: Makes sure that the true file size is the same (or larger) * than the end-of-address. @@ -862,23 +869,24 @@ done: * Programmer: Robb Matzke * Wednesday, August 4, 1999 * - * Modifications: - * *------------------------------------------------------------------------- */ /* ARGSUSED */ static herr_t -H5FD_sec2_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) +H5FD_sec2_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing) { - H5FD_sec2_t *file = (H5FD_sec2_t*)_file; - herr_t ret_value=SUCCEED; /* Return value */ + H5FD_sec2_t *file = (H5FD_sec2_t*)_file; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5FD_sec2_flush, FAIL) + FUNC_ENTER_NOAPI(H5FD_sec2_truncate, FAIL) +#ifdef QAK +HDfprintf(stderr, "%s: file->eof = %a, file->eoa = %a\n", FUNC, file->eof, file->eoa); +#endif /* QAK */ - assert(file); + HDassert(file); /* Extend the file to make sure it's large enough */ - if (file->eoa!=file->eof) { + if(!H5F_addr_eq(file->eoa, file->eof)) { #ifdef _WIN32 HFILE filehandle; /* Windows file handle */ LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */ @@ -889,11 +897,11 @@ H5FD_sec2_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) /* Translate 64-bit integers into form Windows wants */ /* [This algorithm is from the Windows documentation for SetFilePointer()] */ li.QuadPart = (LONGLONG)file->eoa; - (void)SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN); - if(SetEndOfFile((HANDLE)filehandle)==0) + (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN); + if(SetEndOfFile((HANDLE)filehandle) == 0) HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") #else /* _WIN32 */ - if (-1==file_truncate(file->fd, (file_offset_t)file->eoa)) + if(-1 == file_truncate(file->fd, (file_offset_t)file->eoa)) HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") #endif /* _WIN32 */ @@ -903,8 +911,9 @@ H5FD_sec2_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) /* Reset last file I/O information */ file->pos = HADDR_UNDEF; file->op = OP_UNKNOWN; - } + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_sec2_truncate() */ + diff --git a/src/H5FDspace.c b/src/H5FDspace.c index 0bbf160..0fadc1e 100644 --- a/src/H5FDspace.c +++ b/src/H5FDspace.c @@ -66,19 +66,6 @@ /********************/ /* 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); /*********************/ @@ -98,9 +85,6 @@ static haddr_t H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsi /* 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); - /*-------------------------------------------------------------------------- @@ -126,965 +110,127 @@ H5FD_space_init_interface(void) /*------------------------------------------------------------------------- - * 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; - (void)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 + * Function: H5FD_extend * - * Purpose: Try to allocate SIZE bytes of memory from the free list - * if possible. + * Purpose: Extend the EOA space of a file. * - * This is split from H5FD_alloc(). + * NOTE: Returns absolute file offset * - * Return: Success: The format address of the new file memory. + * Return: Success: The address of the previous EOA. * 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; - - (void)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; - - (void)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 */ - (void)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 + * Wednesday, 04. December, 2002 * - * Programmer: Bill Wendling - * 2. December, 2002 + * Modifications: + * Vailin Choi, 29th July 2008 + * Add 2 more parameters for handling alignment: address and size of the fragment * *------------------------------------------------------------------------- */ 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) +H5FD_extend(H5FD_t *file, H5FD_mem_t type, hbool_t new_block, hsize_t size, haddr_t *frag_addr, hsize_t *frag_size) { + haddr_t eoa; /* Address of end-of-allocated space */ + hsize_t extra; /* Extra space to allocate, to align request */ 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 */ + FUNC_ENTER_NOAPI_NOINIT(H5FD_extend) /* 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(file->cls); 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; + /* Get current end-of-allocated space address */ + eoa = file->cls->get_eoa(file, type); - /* 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 */ + /* Compute extra space to allocate, if this is a new block and should be aligned */ + extra = 0; + if(new_block && file->alignment > 1 && size >= file->threshold) { + hsize_t mis_align; /* Amount EOA is misaligned */ + + /* Check for EOA already aligned */ + if((mis_align = (eoa % file->alignment)) > 0) { + extra = file->alignment - mis_align; + if (frag_addr) *frag_addr = eoa; + if (frag_size) *frag_size = extra; + } } /* end if */ - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5FD_aggr_adjoin() */ + /* Add in extra allocation amount */ + size += extra; - -/*------------------------------------------------------------------------- - * 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 for overflow when extending */ + if(H5F_addr_overflow(eoa, size) || (eoa + size) > file->maxaddr) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") - /* Check args */ - HDassert(file); - HDassert(aggr); - HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + /* Set the [possibly aligned] address to return */ + ret_value = eoa + extra; - /* 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 */ + /* Extend the end-of-allocated space address */ + eoa += size; + if(file->cls->set_eoa(file, type, eoa) < 0) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed") 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() */ +} /* end H5FD_extend() */ /*------------------------------------------------------------------------- - * 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 + * Function: H5FD_alloc * - *------------------------------------------------------------------------- - */ -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: Private version of H5FDalloc(). * - * Purpose: Double private version of H5FDalloc() :-) + * Return: Success: The format address of the new file memory. + * Failure: The undefined address HADDR_UNDEF * - * Return: Success: The format address of the new file memory. - * Failure: The undefined address HADDR_UNDEF + * Programmer: Robb Matzke + * Wednesday, August 4, 1999 * - * Programmer: Quincey Koziol - * Friday, August 25, 2000 + * Modification: + * Vailin Choi, 29th July 2008 + * Add two more parameters () for handling alignment: address & size of the fragment * *------------------------------------------------------------------------- */ -static haddr_t -H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) +haddr_t +H5FD_alloc(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, hsize_t size, haddr_t *frag_addr, hsize_t *frag_size) { - haddr_t ret_value = HADDR_UNDEF; + haddr_t ret_value = HADDR_UNDEF; - FUNC_ENTER_NOAPI_NOINIT(H5FD_real_alloc) + 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); + HDassert(file); + HDassert(file->cls); + HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + HDassert(size > 0); - /* - * Dispatch to driver `alloc' callback or extend the end-of-address - * marker - */ + /* 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) + } /* end if */ + else { + if((ret_value = H5FD_extend(file, type, TRUE, size, frag_addr, frag_size)) == HADDR_UNDEF) HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver eoa update request failed") - } + } /* end else */ + + /* Convert absolute file offset to relative address */ + ret_value -= file->base_addr; 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() */ +} /* end H5FD_alloc() */ /*------------------------------------------------------------------------- @@ -1101,9 +247,8 @@ done: *------------------------------------------------------------------------- */ herr_t -H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size) +H5FD_free(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, hsize_t size) { - H5FD_mem_t mapped_type; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FD_free, FAIL) @@ -1112,235 +257,50 @@ H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t si HDassert(file); HDassert(file->cls); HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + HDassert(size > 0); #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 */ - (void)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; + /* Sanity checking */ + if(!H5F_addr_defined(addr)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file offset") - /* 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; + /* Convert address to absolute file offset */ + addr += file->base_addr; - /* Check for eliminating the block before the 'current' one */ - if(last == prev) - prev = last_prev; + /* More sanity checking */ + if(addr > file->maxaddr || H5F_addr_overflow(addr, size) || (addr + size) > file->maxaddr) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file free space region to free") - /* Free the memory for the merged block */ - (void)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 for file driver 'free' callback and call it if available */ + if(file->cls->free) { #ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: mapped_type = %u, last = {%a, %Hu}\n", FUNC, (unsigned)mapped_type, last->addr, last->size); +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_CANTFREE, FAIL, "driver free request failed") + } /* end if */ + /* Check if this free block is at the end of file allocated space. + * Truncate it if this is true. + */ + else if(file->cls->get_eoa) { + haddr_t eoa; - /* 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); + 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)) { + if(eoa == (addr + size)) { #ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, last->addr); +HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, 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*/ - (void)H5FL_FREE(H5FD_free_t, last); - } /* end if */ + if(file->cls->set_eoa(file, type, addr) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "set end of space allocation request failed") } /* 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 { + } /* end else-if */ + else { /* leak memory */ #ifdef H5FD_ALLOC_DEBUG HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size); @@ -1353,386 +313,55 @@ 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 - * - *------------------------------------------------------------------------- - */ -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 = (uint8_t *)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 + * Function: H5FD_try_extend * - * Purpose: Check if a block in the file can be extended. + * Purpose: Extend a block at the end of the file, if possible. * - * Return: Success: TRUE(1)/FALSE(0) + * Return: Success: TRUE(1) - Block was extended + * FALSE(0) - Block could not be extended * 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 */ - (void)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 + * Thursday, 17. January, 2008 * - * Note: - * Raymond Lu - * 5 January 2007 - * Due to the complexity EOA for Multi driver, this function - * is made failed for now. + * Modification: + * Vailin Choi, 29th July 2008 + * Two more parameters were added to FD_extend() for handling alignment * *------------------------------------------------------------------------- */ -hssize_t -H5FD_get_freespace(const H5FD_t *file) +htri_t +H5FD_try_extend(H5FD_t *file, H5FD_mem_t type, haddr_t blk_end, hsize_t extra_requested) { - 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 */ + haddr_t eoa; /* End of allocated space in file */ + htri_t ret_value = FALSE; /* Return value */ - FUNC_ENTER_NOAPI(H5FD_get_freespace, FAIL) + FUNC_ENTER_NOAPI(H5FD_try_extend, FAIL) /* check args */ HDassert(file); HDassert(file->cls); + HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); + HDassert(extra_requested > 0); - /* 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); + /* Retrieve the end of the address space */ + if(HADDR_UNDEF == (eoa = file->cls->get_eoa(file, type))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed") - /* 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 */ + /* Adjust block end by base address of the file, to create absolute address */ + blk_end += file->base_addr; - /* 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 if the block is exactly at the end of the file */ + if(H5F_addr_eq(blk_end, eoa)) { + /* Extend the object by extending the underlying file */ + if(HADDR_UNDEF == H5FD_extend(file, type, FALSE, extra_requested, NULL, NULL)) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "driver extend request failed") - /* 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; + /* Indicate success */ + HGOTO_DONE(TRUE) } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_get_freespace() */ +} /* end H5FD_try_extend() */ diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c index 46c8e81..59056c9 100644 --- a/src/H5FDstdio.c +++ b/src/H5FDstdio.c @@ -166,6 +166,7 @@ static herr_t H5FD_stdio_read(H5FD_t *lf, H5FD_mem_t type, hid_t fapl_id, haddr_ static herr_t H5FD_stdio_write(H5FD_t *lf, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size, const void *buf); static herr_t H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing); +static herr_t H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); static const H5FD_class_t H5FD_stdio_g = { "stdio", /*name */ @@ -194,6 +195,7 @@ static const H5FD_class_t H5FD_stdio_g = { H5FD_stdio_read, /*read */ H5FD_stdio_write, /*write */ H5FD_stdio_flush, /*flush */ + H5FD_stdio_truncate, /*truncate */ NULL, /*lock */ NULL, /*unlock */ H5FD_FLMAP_SINGLE /*fl_map */ @@ -943,19 +945,63 @@ H5FD_stdio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, * Programmer: Robb Matzke * Wednesday, October 22, 1997 * - * Modifications: - * Ported to VFL/H5FD layer - QAK, 10/18/99 - * *------------------------------------------------------------------------- */ static herr_t H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing) { H5FD_stdio_t *file = (H5FD_stdio_t*)_file; - static const char *func="H5FD_stdio_flush"; /* Function Name for error reporting */ + static const char *func = "H5FD_stdio_flush"; /* Function Name for error reporting */ /* Shut compiler up */ - dxpl_id=dxpl_id; + dxpl_id = dxpl_id; + + /* Clear the error stack */ + H5Eclear2(H5E_DEFAULT); + + /* Only try to flush the file if we have write access */ + if(file->write_access) { + /* Flush */ + if(!closing) { + if(fflush(file->fp) < 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fflush failed", -1) + + /* Reset last file I/O information */ + file->pos = HADDR_UNDEF; + file->op = H5FD_STDIO_OP_UNKNOWN; + } /* end if */ + } /* end if */ + + return(0); +} /* end H5FD_stdio_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_stdio_truncate + * + * Purpose: Makes sure that the true file size is the same (or larger) + * than the end-of-address. + * + * Errors: + * IO SEEKERROR fseek failed. + * IO WRITEERROR fflush or fwrite failed. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Thursday, January 31, 2008 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing) +{ + H5FD_stdio_t *file = (H5FD_stdio_t*)_file; + static const char *func = "H5FD_stdio_truncate"; /* Function Name for error reporting */ + + /* Shut compiler up */ + dxpl_id = dxpl_id; + closing = closing; /* Clear the error stack */ H5Eclear2(H5E_DEFAULT); @@ -963,9 +1009,10 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing) /* Only try to flush the file if we have write access */ if(file->write_access) { /* Makes sure that the true file size is the same as the end-of-address. */ - if (file->eoa!=file->eof) { + if(file->eoa != file->eof) { + int fd = fileno(file->fp); /* File descriptor for HDF5 file */ + #ifdef _WIN32 - int fd=_fileno(file->fp); /* File descriptor for HDF5 file */ HFILE filehandle; /* Windows file handle */ LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */ @@ -975,14 +1022,16 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing) /* Translate 64-bit integers into form Windows wants */ /* [This algorithm is from the Windows documentation for SetFilePointer()] */ li.QuadPart = (LONGLONG)file->eoa; - (void)SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN); - if(SetEndOfFile((HANDLE)filehandle)==0) - H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to extend file properly", -1) + (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN); + if(SetEndOfFile((HANDLE)filehandle) == 0) + H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1) #else /* _WIN32 */ - int fd=fileno(file->fp); /* File descriptor for HDF5 file */ + /* Reset seek offset to beginning of file, so that file isn't re-extended later */ + rewind(file->fp); - if (-1==file_truncate(fd, (file_offset_t)file->eoa)) - H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to extend file properly", -1) + /* Truncate file to proper length */ + if(-1 == file_truncate(fd, (file_offset_t)file->eoa)) + H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1) #endif /* _WIN32 */ /* Update the eof value */ @@ -992,23 +1041,15 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing) file->pos = HADDR_UNDEF; file->op = H5FD_STDIO_OP_UNKNOWN; } /* end if */ - - /* - * Flush - */ - if(!closing) { - if (fflush(file->fp) < 0) - H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fflush failed", -1) - } /* end if */ } /* end if */ else { /* Double-check for problems */ - if (file->eoa>file->eof) + if(file->eoa > file->eof) H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_TRUNCATED, "eoa>eof!", -1) } /* end else */ return(0); -} +} /* end H5FD_stdio_truncate() */ #ifdef _H5private_H @@ -1019,3 +1060,4 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing) */ #error "Do not use HDF5 private definitions" #endif + diff --git a/src/H5FDwindows.c b/src/H5FDwindows.c index bbae92c..912c721 100644 --- a/src/H5FDwindows.c +++ b/src/H5FDwindows.c @@ -139,11 +139,12 @@ static herr_t H5FD_windows_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, h static herr_t H5FD_windows_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size, const void *buf); static herr_t H5FD_windows_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing); +static herr_t H5FD_windows_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); static const H5FD_class_t H5FD_windows_g = { - "windows", /*name */ - MAXADDR, /*maxaddr */ - H5F_CLOSE_WEAK, /* fc_degree */ + "windows", /*name */ + MAXADDR, /*maxaddr */ + H5F_CLOSE_WEAK, /* fc_degree */ NULL, /*sb_size */ NULL, /*sb_encode */ NULL, /*sb_decode */ @@ -154,22 +155,23 @@ static const H5FD_class_t H5FD_windows_g = { 0, /*dxpl_size */ NULL, /*dxpl_copy */ NULL, /*dxpl_free */ - H5FD_windows_open, /*open */ - H5FD_windows_close, /*close */ - H5FD_windows_cmp, /*cmp */ - H5FD_windows_query, /*query */ + H5FD_windows_open, /*open */ + H5FD_windows_close, /*close */ + H5FD_windows_cmp, /*cmp */ + H5FD_windows_query, /*query */ NULL, /*alloc */ NULL, /*free */ - H5FD_windows_get_eoa, /*get_eoa */ - H5FD_windows_set_eoa, /*set_eoa */ - H5FD_windows_get_eof, /*get_eof */ - H5FD_windows_get_handle,/*get_handle */ - H5FD_windows_read, /*read */ - H5FD_windows_write, /*write */ - H5FD_windows_flush, /*flush */ - NULL, /*lock */ - NULL, /*unlock */ - H5FD_FLMAP_SINGLE /*fl_map */ + H5FD_windows_get_eoa, /*get_eoa */ + H5FD_windows_set_eoa, /*set_eoa */ + H5FD_windows_get_eof, /*get_eof */ + H5FD_windows_get_handle, /*get_handle */ + H5FD_windows_read, /*read */ + H5FD_windows_write, /*write */ + H5FD_windows_flush, /*flush */ + H5FD_windows_truncate, /*truncate */ + NULL, /*lock */ + NULL, /*unlock */ + H5FD_FLMAP_SINGLE /*fl_map */ }; /* Declare a free list to manage the H5FD_windows_t struct */ @@ -941,22 +943,20 @@ done: FUNC_LEAVE_NOAPI(ret_value) } + /*------------------------------------------------------------------------- * Function: H5FD_windows_flush * * Purpose: Makes sure that the true file size is the same (or larger) - * than the end-of-address. + * than the end-of-address. * * Return: Success: Non-negative - * - * Failure: Negative + * Failure: Negative * * Programmer: Scott Wegner - * Based on code by Robb Matzke + * Based on code by Robb Matzke * Thursday, May 24 2007 * - * Modifications: - * *------------------------------------------------------------------------- */ /* ARGSUSED */ @@ -964,58 +964,96 @@ static herr_t H5FD_windows_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing) { H5FD_windows_t *file = (H5FD_windows_t*)_file; - herr_t ret_value=SUCCEED; /* Return value */ -#ifndef WINDOWS_USE_STDIO - LARGE_INTEGER li; - HANDLE filehandle; -#else - int fd; -#endif /* WINDOWS_USE_STDIO */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FD_windows_flush, FAIL) - assert(file); + HDassert(file); + + /* Only try to flush if we have write access */ + if(file->write_access) { + /* Flush */ + if(!closing) { +#ifdef WINDOWS_USE_STDIO + if(fflush(file->fp) == EOF) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "fflush failed") +#endif /* WINDOWS_USE_STDIO */ + + /* Reset last file I/O information */ + file->pos = HADDR_UNDEF; + file->op = OP_UNKNOWN; + } /* end if */ + } /* end if */ - if (file->eoa != file->eof) { +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_windows_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_windows_truncate + * + * Purpose: Makes sure that the true file size is the same (or larger) + * than the end-of-address. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Scott Wegner + * Based on code by Robb Matzke + * Thursday, May 24 2007 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +static herr_t +H5FD_windows_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing) +{ + H5FD_windows_t *file = (H5FD_windows_t*)_file; #ifndef WINDOWS_USE_STDIO + LARGE_INTEGER li; + HANDLE filehandle; +#else + int fd; +#endif /* WINDOWS_USE_STDIO */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Extend the file to make sure it's large enough */ - if( (filehandle = (HANDLE)_get_osfhandle(file->fd)) == INVALID_HANDLE_VALUE) - HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to get file handle for file") + FUNC_ENTER_NOAPI(H5FD_windows_truncate, FAIL) - li.QuadPart = (__int64)file->eoa; - (void)SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN); - if(SetEndOfFile(filehandle) == 0) - HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") + HDassert(file); + if(file->eoa != file->eof) { +#ifndef WINDOWS_USE_STDIO + /* Extend the file to make sure it's large enough */ + if((filehandle = (HANDLE)_get_osfhandle(file->fd)) == INVALID_HANDLE_VALUE) + HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to get file handle for file") + + li.QuadPart = (__int64)file->eoa; + (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN); + if(SetEndOfFile(filehandle) == 0) + HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") #else /* WINDOWS_USE_STDIO */ - /* Only try to flush if we have write access */ - if(!file->write_access) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush without write access") - - if((fd = _fileno(file->fp)) == -1) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to get file descriptor for file") - if(_chsize_s(fd, file->eoa)) - HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") - - /* Flush */ - if(!closing) - if (fflush(file->fp) == EOF) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "fflush failed") + /* Only try to flush if we have write access */ + if(!file->write_access) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush without write access") + + if((fd = _fileno(file->fp)) == -1) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to get file descriptor for file") + if(_chsize_s(fd, file->eoa)) + HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") #endif /* WINDOWS_USE_STDIO */ - /* Update the eof value */ - file->eof = file->eoa; - - /* Reset last file I/O information */ - file->pos = HADDR_UNDEF; - file->op = OP_UNKNOWN; + /* Update the eof value */ + file->eof = file->eoa; - } + /* Reset last file I/O information */ + file->pos = HADDR_UNDEF; + file->op = OP_UNKNOWN; + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD_windows_truncate() */ #endif /* H5_HAVE_WINDOWS */ @@ -91,22 +91,25 @@ H5FL_DEFINE(H5FS_t); * Programmer: Quincey Koziol * Tuesday, March 7, 2006 * + * Modifications: + * Vailin Choi, July 29th, 2008 + * Add two more parameters for handling alignment: alignment & threshhold + * *------------------------------------------------------------------------- */ H5FS_t * H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_create, - size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata) + size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold) { H5FS_t *fspace = NULL; /* New free space structure */ H5FS_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5FS_create, NULL) -#ifdef QAK +#ifdef H5FS_DEBUG HDfprintf(stderr, "%s: Creating free space manager, nclasses = %Zu\n", FUNC, nclasses); -#endif /* QAK */ +#endif /* H5FS_DEBUG */ /* Check arguments. */ - HDassert(fs_addr); HDassert(fs_create->shrink_percent); HDassert(fs_create->shrink_percent < fs_create->expand_percent); HDassert(fs_create->max_sect_size); @@ -118,11 +121,6 @@ HDfprintf(stderr, "%s: Creating free space manager, nclasses = %Zu\n", FUNC, ncl if(NULL == (fspace = H5FS_new(nclasses, classes, cls_init_udata))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space free list") - /* Allocate space for the free space header */ - if(HADDR_UNDEF == (fspace->addr = H5MF_alloc(f, H5FD_MEM_FSPACE_HDR, dxpl_id, (hsize_t)H5FS_HEADER_SIZE(f)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for free space header") - *fs_addr = fspace->addr; - /* Initialize creation information for free space manager */ fspace->client = fs_create->client; fspace->shrink_percent = fs_create->shrink_percent; @@ -130,17 +128,39 @@ HDfprintf(stderr, "%s: Creating free space manager, nclasses = %Zu\n", FUNC, ncl fspace->max_sect_addr = fs_create->max_sect_addr; fspace->max_sect_size = fs_create->max_sect_size; - /* Cache the new free space header (pinned) */ - if(H5AC_set(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, fspace, H5AC__PIN_ENTRY_FLAG) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space header to cache") + fspace->alignment = alignment; + fspace->threshold = threshold; + + /* Check if the free space tracker is supposed to be persistant */ + if(fs_addr) { + /* Allocate space for the free space header */ + if(HADDR_UNDEF == (fspace->addr = H5MF_alloc(f, H5FD_MEM_FSPACE_HDR, dxpl_id, (hsize_t)H5FS_HEADER_SIZE(f)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for free space header") + + /* Cache the new free space header (pinned) */ + if(H5AC_set(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, fspace, H5AC__PIN_ENTRY_FLAG) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space header to cache") + + /* Return free space header address to caller, if desired */ + *fs_addr = fspace->addr; + } /* end if */ + + /* Set the reference count to 1, since we inserted the entry in the cache pinned */ + fspace->rc = 1; /* Set the return value */ ret_value = fspace; +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: fspace = %p, fspace->addr = %a\n", FUNC, fspace, fspace->addr); +#endif /* H5FS_DEBUG */ done: if(!ret_value && fspace) (void)H5FS_cache_hdr_dest(f, fspace); +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value); +#endif /* H5FS_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_create() */ @@ -157,21 +177,25 @@ done: * Programmer: Quincey Koziol * Tuesday, May 2, 2006 * + * Modfications: + * + * Vailin Choi, July 29th, 2008 + * Add two more parameters for handling alignment: alignment & threshhold + * *------------------------------------------------------------------------- */ H5FS_t * H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, size_t nclasses, - const H5FS_section_class_t *classes[], void *cls_init_udata) + const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold) { H5FS_t *fspace = NULL; /* New free space structure */ H5FS_prot_t fs_prot; /* Information for protecting free space manager */ - unsigned fspace_status = 0; /* Free space header's status in the metadata cache */ H5FS_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5FS_open, NULL) -#ifdef QAK -HDfprintf(stderr, "%s: Opening free space manager, nclasses = %Zu\n", FUNC, nclasses); -#endif /* QAK */ +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Opening free space manager, fs_addr = %a, nclasses = %Zu\n", FUNC, fs_addr, nclasses); +#endif /* H5FS_DEBUG */ /* Check arguments. */ HDassert(H5F_addr_defined(fs_addr)); @@ -186,26 +210,23 @@ HDfprintf(stderr, "%s: Opening free space manager, nclasses = %Zu\n", FUNC, ncla /* Protect the free space header */ if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &fs_prot, NULL, H5AC_READ))) HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, NULL, "unable to load free space header") -#ifdef QAK +#ifdef H5FS_DEBUG HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", FUNC, fspace->sect_addr); HDfprintf(stderr, "%s: fspace->sect_size = %Hu\n", FUNC, fspace->sect_size); HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", FUNC, fspace->alloc_sect_size); HDfprintf(stderr, "%s: fspace->sinfo = %p\n", FUNC, fspace->sinfo); -#endif /* QAK */ +HDfprintf(stderr, "%s: fspace->rc = %u\n", FUNC, fspace->rc); +#endif /* H5FS_DEBUG */ - /* Check the free space header's status in the metadata cache */ - if(H5AC_get_entry_status(f, fs_addr, &fspace_status) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, NULL, "unable to check metadata cache status for free space header") + /* Increment the reference count on the free space manager header */ + HDassert(fspace->rc <= 1); + if(H5FS_incr(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINC, NULL, "unable to increment ref. count on free space header") - /* If the free space header isn't already pinned, pin it now */ - /* (could still be pinned from it's section info still hanging around in the cache) */ - if(!(fspace_status & H5AC_ES__IS_PINNED)) { - /* Pin free space header in the cache */ - if(H5AC_pin_protected_entry(f, fspace) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, NULL, "unable to pin free space header") - } /* end if */ + fspace->alignment = alignment; + fspace->threshold = threshold; - /* Unlock free space header, now pinned */ + /* Unlock free space header */ if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, NULL, "unable to release free space header") @@ -239,9 +260,9 @@ H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr) herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FS_delete, FAIL) -#ifdef QAK -HDfprintf(stderr, "%s: Deleting free space manager\n", FUNC); -#endif /* QAK */ +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Deleting free space manager, fs_addr = %a\n", FUNC, fs_addr); +#endif /* H5FS_DEBUG */ /* Check arguments. */ HDassert(f); @@ -257,16 +278,19 @@ HDfprintf(stderr, "%s: Deleting free space manager\n", FUNC); if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &fs_prot, NULL, H5AC_WRITE))) HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to protect free space header") + /* Sanity check */ + HDassert(fspace->sinfo == NULL); + /* Delete serialized section storage, if there are any */ -#ifdef QAK +#ifdef H5FS_DEBUG HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", FUNC, fspace->sect_addr); -#endif /* QAK */ +#endif /* H5FS_DEBUG */ if(fspace->serial_sect_count > 0) { unsigned sinfo_status = 0; /* Free space section info's status in the metadata cache */ /* Sanity check */ HDassert(H5F_addr_defined(fspace->sect_addr)); - HDassert(fspace->sect_size > 0); + HDassert(fspace->alloc_sect_size > 0); /* Check the free space section info's status in the metadata cache */ if(H5AC_get_entry_status(f, fspace->sect_addr, &sinfo_status) < 0) @@ -278,32 +302,28 @@ HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", FUNC, fspace->sect_addr); HDassert(!(sinfo_status & H5AC_ES__IS_PINNED)); HDassert(!(sinfo_status & H5AC_ES__IS_PROTECTED)); -#ifdef QAK +#ifdef H5FS_DEBUG HDfprintf(stderr, "%s: Expunging free space section info from cache\n", FUNC); -#endif /* QAK */ +#endif /* H5FS_DEBUG */ /* Evict the free space section info from the metadata cache */ - if(H5AC_expunge_entry(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr) < 0) + /* (Free file space) */ + if(H5AC_expunge_entry(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove free space section info from cache") -#ifdef QAK +#ifdef H5FS_DEBUG HDfprintf(stderr, "%s: Done expunging free space section info from cache\n", FUNC); -#endif /* QAK */ +#endif /* H5FS_DEBUG */ } /* end if */ - - /* Release the space in the file */ - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections") + else { + /* Release the space in the file */ + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections") + } /* end else */ } /* end if */ - /* Release header's disk space */ - if(H5MF_xfree(f, H5FD_MEM_FSPACE_HDR, dxpl_id, fs_addr, (hsize_t)H5FS_HEADER_SIZE(f))<0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space header") - - /* Release the free space header */ - if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__DELETED_FLAG) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space header") - fspace = NULL; - done: + if(fspace && H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) + HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space header") + FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_delete() */ @@ -333,72 +353,143 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) /* Check arguments. */ HDassert(f); HDassert(fspace); -#ifdef QAK -HDfprintf(stderr, "%s: Entering, fspace = %p, fspace->sinfo = %p\n", FUNC, fspace, fspace->sinfo); -#endif /* QAK */ +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Entering, fspace = %p, fspace->addr = %a, fspace->sinfo = %p\n", FUNC, fspace, fspace->addr, fspace->sinfo); +#endif /* H5FS_DEBUG */ /* Check if section info is valid */ + /* (i.e. the header "owns" the section info and it's not in the cache) */ if(fspace->sinfo) { - HDassert(H5F_addr_defined(fspace->sect_addr)); - - /* Unpin the free space section info in the cache */ - if(H5AC_unpin_entry(f, fspace->sinfo) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space section info") - - /* If there aren't any sections being managed, free the space for the sections */ -#ifdef QAK -HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count); -#endif /* QAK */ - if(fspace->tot_sect_count == 0) { - haddr_t old_addr; /* Old section info address */ - - HDassert(fspace->serial_sect_count == 0); - HDassert(fspace->ghost_sect_count == 0); - - /* Free previous serialized sections disk space */ - old_addr = fspace->sect_addr; - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_addr, fspace->alloc_sect_size) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections") +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu, fspace->serial_sect_count = %Hu, fspace->sect_addr = %a, fspace->rc = %u\n", FUNC, fspace->tot_sect_count, fspace->serial_sect_count, fspace->sect_addr, fspace->rc); +HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size); +#endif /* H5FS_DEBUG */ + /* If there are sections to serialize, update them */ + /* (if the free space manager is persistant) */ + if(fspace->serial_sect_count > 0 && H5F_addr_defined(fspace->addr)) { +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Real sections to store in file\n", FUNC); +#endif /* H5FS_DEBUG */ + if(fspace->sinfo->dirty) { + /* Check if the section info is "floating" */ + if(!H5F_addr_defined(fspace->sect_addr)) { + /* Sanity check */ + HDassert(fspace->sect_size > 0); + + /* Allocate space for the section info in file */ + if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size))) + HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") + fspace->alloc_sect_size = (size_t)fspace->sect_size; + + /* Mark free space header as dirty */ + if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") + } /* end if */ + } /* end if */ + else + /* Sanity check that section info has address */ + HDassert(H5F_addr_defined(fspace->sect_addr)); + + /* Cache the free space section info */ + if(H5AC_set(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space sections to cache") + } /* end if */ + else { +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: NOT storing section info in file\n", FUNC); +#endif /* H5FS_DEBUG */ + /* Check if space for the section info is allocated */ + if(H5F_addr_defined(fspace->sect_addr)) { + /* Sanity check */ + /* (section info should only be in the file if the header is */ + HDassert(H5F_addr_defined(fspace->addr)); - /* Reset section info */ - fspace->sect_addr = HADDR_UNDEF; - fspace->alloc_sect_size = fspace->sect_size = 0; +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Section info allocated though\n", FUNC); +#endif /* H5FS_DEBUG */ + /* Check if the section info is for the free space in the file */ + /* (NOTE: This is the "bootstrapping" special case for the + * free space manager, to avoid freeing the space for the + * section info and re-creating it as a section in the + * manager. -QAK) + */ + if(fspace->client == H5FS_CLIENT_FILE_ID) { + htri_t status; /* "can absorb" status for section into */ - /* Mark free space header as dirty */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Section info is for file free space\n", FUNC); +#endif /* H5FS_DEBUG */ + /* Try to shrink the file or absorb the section info into a block aggregator */ + if((status = H5MF_try_shrink(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size)) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for absorbing section info") + else if(status == FALSE) { + /* Section info can't "go away", but it's free. Allow + * header to record it + */ +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Section info can't 'go away', header will own it\n", FUNC); +#endif /* H5FS_DEBUG */ + } /* end if */ + else { +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Section info went 'go away'\n", FUNC); +#endif /* H5FS_DEBUG */ + /* Reset section info in header */ + fspace->sect_addr = HADDR_UNDEF; + fspace->alloc_sect_size = 0; + + /* Mark free space header as dirty */ + if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") + } /* end else */ + } /* end if */ + else { + haddr_t old_sect_addr = fspace->sect_addr; /* Previous location of section info in file */ + hsize_t old_alloc_sect_size = fspace->alloc_sect_size; /* Previous size of section info in file */ - /* Evict the section info from the metadata cache */ - if(H5AC_expunge_entry(f, dxpl_id, H5AC_FSPACE_SINFO, old_addr) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "unable to remove free space section info from cache") - } /* end if */ +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Section info is NOT for file free space\n", FUNC); +#endif /* H5FS_DEBUG */ + /* Reset section info in header */ + fspace->sect_addr = HADDR_UNDEF; + fspace->alloc_sect_size = 0; + + /* Mark free space header as dirty */ + if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") + + /* Free previous serialized sections disk space */ + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_sect_addr, old_alloc_sect_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections") + } /* end if */ + } /* end else */ + + /* Destroy section info */ + if(H5FS_cache_sinfo_dest(f, fspace->sinfo) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "unable to destroy free space section info") + } /* end else */ + + /* Reset the header's pointer to the section info */ + fspace->sinfo = NULL; } /* end if */ else { - unsigned sect_status = 0; /* Free space section's status in the metadata cache */ - - /* 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 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 */ - /* (the section info destructor would unpin it if the section info existed) */ - if(H5AC_unpin_entry(f, fspace) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header") - } /* end if */ + /* Just sanity checks... */ + if(fspace->serial_sect_count > 0) + /* Sanity check that section info has address */ + HDassert(H5F_addr_defined(fspace->sect_addr)); + else + /* Sanity check that section info doesn't have address */ + HDassert(!H5F_addr_defined(fspace->sect_addr)); } /* end else */ - /* Reset the header's pointer to the section info, so it will get pinned again - * if the free space header is still in the metadata cache when the free - * space manager is re-opened. - */ - fspace->sinfo = NULL; + /* Decrement the reference count on the free space manager header */ + if(H5FS_decr(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDEC, FAIL, "unable to decrement ref. count on free space header") done: +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Leaving, ret_value = %d, fspace->rc = %u\n", FUNC, ret_value, fspace->rc); +#endif /* H5FS_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_close() */ @@ -453,6 +544,10 @@ H5FS_new(size_t nclasses, const H5FS_section_class_t *classes[], if(fspace->sect_cls[u].init_cls) if((fspace->sect_cls[u].init_cls)(&fspace->sect_cls[u], cls_init_udata) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "unable to initialize section class") + + /* Determine maximum class-specific serialization size for each section */ + if(fspace->sect_cls[u].serial_size > fspace->max_cls_serial_size) + fspace->max_cls_serial_size = fspace->sect_cls[u].serial_size; } /* end for */ } /* end if */ @@ -494,12 +589,141 @@ H5FS_size(const H5F_t *f, const H5FS_t *fspace, hsize_t *meta_size) HDassert(meta_size); /* Get the free space size info */ - *meta_size += H5FS_HEADER_SIZE(f) + fspace->alloc_sect_size; + *meta_size += H5FS_HEADER_SIZE(f) + (fspace->sinfo ? fspace->sect_size : fspace->alloc_sect_size); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5FS_size() */ + +/*------------------------------------------------------------------------- + * Function: H5FS_incr + * + * Purpose: Increment reference count on free space header + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * February 7, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_incr(H5F_t *f, H5FS_t *fspace) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_incr, FAIL) #ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Entering, fpace->addr = %a, fspace->rc = %u\n", FUNC, fspace->addr, fspace->rc); +#endif /* H5FS_DEBUG */ + + /* + * Check arguments. + */ + HDassert(f); + HDassert(fspace); + + /* Check if we should pin the header in the cache */ + if(fspace->rc == 0 && H5F_addr_defined(fspace->addr)) + if(H5AC_pin_protected_entry(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, FAIL, "unable to pin free space header") + + /* Increment reference count on header */ + fspace->rc++; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FS_incr() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_decr + * + * Purpose: Decrement reference count on free space header + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * February 7, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_decr(H5F_t *f, H5FS_t *fspace) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_decr, FAIL) +#ifdef H5FS_DEBUG +HDfprintf(stderr, "%s: Entering, fpace->addr = %a, fspace->rc = %u\n", FUNC, fspace->addr, fspace->rc); +#endif /* H5FS_DEBUG */ + + /* + * Check arguments. + */ + HDassert(f); + HDassert(fspace); + + /* Decrement reference count on header */ + fspace->rc--; + + /* Check if we should unpin the header in the cache */ + if(fspace->rc == 0) { + if(H5F_addr_defined(fspace->addr)) { + if(H5AC_unpin_entry(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header") + } /* end if */ + else { + if(H5FS_cache_hdr_dest(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "unable to destroy free space header") + } /* end else */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FS_decr() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_dirty + * + * Purpose: Mark free space header as dirty + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Feb 14 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_dirty(H5F_t *f, H5FS_t *fspace) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_dirty) +#ifdef QAK +HDfprintf(stderr, "%s: Marking free space header as dirty\n", FUNC); +#endif /* QAK */ + + /* Sanity check */ + HDassert(f); + HDassert(fspace); + + /* Check if the free space manager is persistant */ + if(H5F_addr_defined(fspace->addr)) + /* Mark header as dirty in cache */ + if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FS_dirty() */ + +#ifdef H5FS_DEBUG_ASSERT /*------------------------------------------------------------------------- * Function: H5FS_assert @@ -518,16 +742,19 @@ herr_t H5FS_assert(const H5FS_t *fspace) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_assert) -#ifdef QAK -HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", "H5FS_assert", fspace->hdr->tot_sect_count); +#ifndef QAK +HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", "H5FS_assert", fspace->tot_sect_count); #endif /* QAK */ - /* Sanity check sections */ - H5FS_sect_assert(fspace); + /* Checks for section info, if it's available */ + if(fspace->sinfo) { + /* Sanity check sections */ + H5FS_sect_assert(fspace); - /* General assumptions about the section size counts */ - HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->serial_size_count); - HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->ghost_size_count); + /* General assumptions about the section size counts */ + HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->serial_size_count); + HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->ghost_size_count); + } /* end if */ /* General assumptions about the section counts */ HDassert(fspace->tot_sect_count >= fspace->serial_sect_count); @@ -539,5 +766,4 @@ HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", "H5FS_assert", fspa FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5FS_assert() */ -#endif /* H5FS_DEBUG */ - +#endif /* H5FS_DEBUG_ASSERT */ diff --git a/src/H5FScache.c b/src/H5FScache.c index edf045a..a7af72b 100644 --- a/src/H5FScache.c +++ b/src/H5FScache.c @@ -36,6 +36,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5FSpkg.h" /* File free space */ +#include "H5MFprivate.h" /* File memory management */ #include "H5Vprivate.h" /* Vectors and arrays */ #include "H5WBprivate.h" /* Wrapped Buffers */ @@ -299,12 +300,68 @@ H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5F FUNC_ENTER_NOAPI_NOINIT(H5FS_cache_hdr_flush) #ifdef QAK HDfprintf(stderr, "%s: Flushing free space header, addr = %a, destroy = %u\n", FUNC, addr, (unsigned)destroy); +HDfprintf(stderr, "%s: fspace->sect_addr = %a, fspace->sinfo = %p\n", FUNC, fspace->sect_addr, fspace->sinfo); +HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size); #endif /* QAK */ /* check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); HDassert(fspace); + HDassert(H5F_addr_defined(fspace->addr)); + + /* Check if the header "owns" the section info */ + if(fspace->sinfo) { + /* Sanity check - should not be trying to destroy header if it still + * "owns" section info + */ + HDassert(!destroy); + + /* Check if the section info is dirty */ + if(fspace->sinfo->dirty) { + if(fspace->serial_sect_count > 0) { + /* Check if we need to allocate space for section info */ + if(!H5F_addr_defined(fspace->sect_addr)) { + /* Sanity check */ + HDassert(fspace->sect_size > 0); + + /* Allocate space for the section info in file */ + if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size))) + HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") + fspace->alloc_sect_size = (size_t)fspace->sect_size; + + /* Mark header dirty */ + /* (don't use cache API, since we're in a callback) */ + fspace->cache_info.is_dirty = TRUE; + } /* end if */ + + /* Write section info to file */ + if(H5FS_cache_sinfo_flush(f, dxpl_id, FALSE, fspace->sect_addr, fspace->sinfo, NULL) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space section info to disk") + } /* end if */ + else { + /* Sanity check that section info doesn't have address */ + HDassert(!H5F_addr_defined(fspace->sect_addr)); + } /* end else */ +#ifdef QAK +HDfprintf(stderr, "%s: Check 2.0\n", FUNC); +HDfprintf(stderr, "%s: fspace->sect_addr = %a, fspace->sinfo = %p\n", FUNC, fspace->sect_addr, fspace->sinfo); +HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size); +#endif /* QAK */ + + /* Mark section info clean */ + fspace->sinfo->dirty = FALSE; + } /* end if */ + } /* end if */ + else { + /* Just sanity checks... */ + if(fspace->serial_sect_count > 0) + /* Sanity check that section info has address */ + HDassert(H5F_addr_defined(fspace->sect_addr)); + else + /* Sanity check that section info doesn't have address */ + HDassert(!H5F_addr_defined(fspace->sect_addr)); + } /* end else */ if(fspace->cache_info.is_dirty) { uint8_t *hdr; /* Pointer to header buffer */ @@ -412,9 +469,8 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ herr_t -H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace) +H5FS_cache_hdr_dest(H5F_t *f, H5FS_t *fspace) { unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -426,6 +482,12 @@ H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace) */ HDassert(fspace); + /* We should not still be holding on to the free space section info */ + HDassert(!fspace->sinfo); + + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!fspace->cache_info.free_file_space_on_destroy || H5F_addr_defined(fspace->cache_info.addr)); + /* Terminate the section classes for this free space list */ for(u = 0; u < fspace->nclasses ; u++) { /* Call the class termination routine, if there is one */ @@ -434,6 +496,17 @@ H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "unable to finalize section class") } /* end for */ + /* Check for freeing file space for free space header */ + if(fspace->cache_info.free_file_space_on_destroy) { + /* Sanity check */ + HDassert(H5F_addr_defined(fspace->addr)); + + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_FSPACE_HDR, H5AC_dxpl_id, fspace->cache_info.addr, (hsize_t)H5FS_HEADER_SIZE(f)) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space header") + } /* end if */ + /* Release the memory for the free space section classes */ if(fspace->sect_cls) fspace->sect_cls = (H5FS_section_class_t *)H5FL_SEQ_FREE(H5FS_section_class_t, fspace->sect_cls); @@ -556,11 +629,6 @@ HDfprintf(stderr, "%s: Load free space sections, addr = %a\n", FUNC, addr); if(NULL == (sinfo = H5FS_sinfo_new(f, fspace))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - /* Link free space manager to section info */ - /* (for deserializing sections) */ - HDassert(fspace->sinfo == NULL); - fspace->sinfo = sinfo; - /* Sanity check address */ if(H5F_addr_ne(addr, fspace->sect_addr)) HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "incorrect address for free space sections") @@ -872,7 +940,7 @@ HDfprintf(stderr, "%s: Flushing free space header, addr = %a, destroy = %u\n", F HDassert(sinfo->fspace); HDassert(sinfo->fspace->sect_cls); - if(sinfo->cache_info.is_dirty) { + if(sinfo->cache_info.is_dirty || sinfo->dirty) { H5FS_iter_ud_t udata; /* User data for callbacks */ uint8_t *buf = NULL; /* Temporary raw data buffer */ uint8_t *p; /* Pointer into raw data buffer */ @@ -944,6 +1012,7 @@ HDfprintf(stderr, "%s: sinfo->fspace->alloc_sect_size = %Hu\n", FUNC, sinfo->fsp (void)H5FL_BLK_FREE(sect_block, buf); sinfo->cache_info.is_dirty = FALSE; + sinfo->dirty = FALSE; } /* end if */ if(destroy) @@ -966,6 +1035,10 @@ done: * Programmer: Quincey Koziol * Saturday, March 11, 2006 * + * Modifications: + * Vailin Choi, July 29th, 2008 + * Add HDassert() to make sure "free" method exists before calling + * *------------------------------------------------------------------------- */ static herr_t @@ -978,6 +1051,7 @@ H5FS_sinfo_free_sect_cb(void *_sect, void UNUSED *key, void *op_data) HDassert(sect); HDassert(sinfo); + HDassert(sinfo->fspace->sect_cls[sect->type].free); /* Call the section's class 'free' method on the section */ (*sinfo->fspace->sect_cls[sect->type].free)(sect); @@ -1033,7 +1107,6 @@ H5FS_sinfo_free_node_cb(void *item, void UNUSED *key, void *op_data) * *------------------------------------------------------------------------- */ -/* ARGSUSED */ herr_t H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo) { @@ -1041,6 +1114,9 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo) herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_cache_sinfo_dest) +#ifdef QAK +HDfprintf(stderr, "%s: Destroying section info, sinfo->fspace->addr = %a\n", FUNC, sinfo->fspace->addr); +#endif /* QAK */ /* * Check arguments. @@ -1049,6 +1125,20 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo) HDassert(sinfo->fspace); HDassert(sinfo->bins); + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!sinfo->cache_info.free_file_space_on_destroy || H5F_addr_defined(sinfo->cache_info.addr)); + + /* Check for freeing file space for free space section info */ + if(sinfo->cache_info.free_file_space_on_destroy) { + /* Sanity check */ + HDassert(sinfo->fspace->alloc_sect_size > 0); + + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, H5AC_dxpl_id, sinfo->cache_info.addr, (hsize_t)sinfo->fspace->alloc_sect_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space section info") + } /* end if */ + /* Clear out lists of nodes */ for(u = 0; u < sinfo->nbins; u++) if(sinfo->bins[u].bin_list) { @@ -1064,12 +1154,14 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo) if(H5SL_close(sinfo->merge_list) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy section merging skip list") - /* Unpin the free space header in the cache */ + /* Decrement the reference count on free space header */ /* (make certain this is last action with section info, to allow for header * disappearing immediately) */ - if(H5AC_unpin_entry(f, sinfo->fspace) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header") + sinfo->fspace->sinfo = NULL; + if(H5FS_decr(f, sinfo->fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDEC, FAIL, "unable to decrement ref. count on free space header") + sinfo->fspace = NULL; /* Release free space section info */ (void)H5FL_FREE(H5FS_sinfo_t, sinfo); @@ -1141,7 +1233,7 @@ H5FS_cache_sinfo_size(const H5F_t UNUSED *f, const H5FS_sinfo_t *sinfo, size_t * HDassert(size_ptr); /* Set size value */ - H5_ASSIGN_OVERFLOW(/* To: */ *size_ptr, /* From: */ sinfo->fspace->sect_size, /* From: */ hsize_t, /* To: */ size_t); + H5_ASSIGN_OVERFLOW(/* To: */ *size_ptr, /* From: */ sinfo->fspace->alloc_sect_size, /* From: */ hsize_t, /* To: */ size_t); FUNC_LEAVE_NOAPI(SUCCEED) } /* H5FS_cache_sinfo_size() */ diff --git a/src/H5FSdbg.c b/src/H5FSdbg.c index b5d2a6f..cf165ca 100644 --- a/src/H5FSdbg.c +++ b/src/H5FSdbg.c @@ -30,6 +30,7 @@ #define H5FS_PACKAGE /*suppress error about including H5FSpkg */ #define H5HF_DEBUGGING /* Need access to fractal heap debugging routines */ +#define H5MF_DEBUGGING /* Need access to file space debugging routines */ /***********/ /* Headers */ @@ -38,6 +39,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5FSpkg.h" /* File free space */ #include "H5HFprivate.h" /* Fractal heaps */ +#include "H5MFprivate.h" /* File memory management */ /****************/ /* Local Macros */ @@ -85,6 +87,10 @@ * koziol@ncsa.uiuc.edu * May 9 2006 * + * Modifications: + * Vailin Choi, July 29th, 2008 + * Add H5FS_CLIENT_FILE_ID for File Memory Management + * *------------------------------------------------------------------------- */ herr_t @@ -124,7 +130,8 @@ H5FS_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int */ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Free space client:", - (fspace->client == H5FS_CLIENT_FHEAP_ID ? "Fractal heap" : "Unknown")); + (fspace->client == H5FS_CLIENT_FHEAP_ID ? "Fractal heap" : + (fspace->client == H5FS_CLIENT_FILE_ID ? "File Memory Management" : "Unknown"))); HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, "Total free space tracked:", fspace->tot_space); @@ -259,7 +266,10 @@ H5FS_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, FILE *stream, int client = fspace->client; /* Release the free space header */ - if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__NO_FLAGS_SET) < 0) + /* (set the "deleted" flag for the unprotect, so the cache entry is removed + * and reloaded later, with the correct client information -QAK) + */ + if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__DELETED_FLAG) < 0) HDONE_ERROR(H5E_FSPACE, H5E_PROTECT, FAIL, "unable to release free space header") fspace = NULL; @@ -275,6 +285,13 @@ H5FS_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, FILE *stream, int HGOTO_ERROR(H5E_FSPACE, H5E_SYSTEM, FAIL, "unable to dump fractal heap free space sections") break; + case H5FS_CLIENT_FILE_ID: +#ifdef NOT_YET + if(H5MF_sects_debug(f, dxpl_id, client_addr, stream, indent + 3, MAX(0, fwidth - 3)) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_SYSTEM, FAIL, "unable to dump file free space sections") +#endif /* NOT_YET */ + break; + default: HDfprintf(stream, "Unknown client!\n"); break; diff --git a/src/H5FSpkg.h b/src/H5FSpkg.h index 9f3409f..1786b44 100644 --- a/src/H5FSpkg.h +++ b/src/H5FSpkg.h @@ -28,9 +28,15 @@ #ifndef _H5FSpkg_H #define _H5FSpkg_H -/* Uncomment this macro to enable extra sanity checking */ +/* Uncomment this macro to enable debugging output for free space manager */ /* #define H5FS_DEBUG */ +/* Uncomment this macro to enable debugging output for free space sections */ +/* #define H5FS_SINFO_DEBUG */ + +/* Uncomment this macro to enable extra sanity checking */ +/* #define H5FS_DEBUG_ASSERT */ + /* Get package's private header */ #include "H5FSprivate.h" /* File free space */ @@ -110,7 +116,7 @@ typedef struct H5FS_node_t { H5SL_t *sect_list; /* Skip list to hold pointers to actual free list section node */ } H5FS_node_t; -/* Information about sections managed */ +/* Free space section info */ typedef struct H5FS_sinfo_t { /* Information for H5AC cache functions, _must_ be first field in structure */ H5AC_info_t cache_info; @@ -119,6 +125,7 @@ typedef struct H5FS_sinfo_t { H5FS_bin_t *bins; /* Array of lists of lists of free sections */ /* Computed/cached values */ + hbool_t dirty; /* Whether this info in memory is out of sync w/info in file */ unsigned nbins; /* Number of bins */ size_t serial_size; /* Total size of all serializable sections */ size_t tot_size_count; /* Total number of differently sized sections */ @@ -133,7 +140,7 @@ typedef struct H5FS_sinfo_t { H5SL_t *merge_list; /* Skip list to hold sections for detecting merges */ } H5FS_sinfo_t; -/* Main free space info */ +/* Free space header info */ struct H5FS_t { /* Information for H5AC cache functions, _must_ be first field in structure */ H5AC_info_t cache_info; @@ -159,8 +166,17 @@ struct H5FS_t { hsize_t alloc_sect_size; /* Allocated size of the section info in the file */ /* Computed/cached values */ + unsigned rc; /* Count of outstanding references to struct */ haddr_t addr; /* Address of free space header on disk */ H5FS_sinfo_t *sinfo; /* Section information */ + unsigned sinfo_lock_count; /* # of times the section info has been locked */ + hbool_t sinfo_protected; /* Whether the section info was protected when locked */ + hbool_t sinfo_modified; /* Whether the section info has been modified while locked */ + H5AC_protect_t sinfo_accmode; /* Access mode for protecting the section info */ + size_t max_cls_serial_size; /* Max. additional size of serialized form of section */ + hsize_t threshold; /* Threshold for alignment */ + hsize_t alignment; /* Alignment */ + /* Memory data structures (not stored directly) */ H5FS_section_class_t *sect_cls; /* Array of section classes for this free list */ @@ -197,6 +213,9 @@ H5FL_EXTERN(H5FS_t); /* Free space manager header routines */ H5_DLL H5FS_t *H5FS_new(size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata); +H5_DLL herr_t H5FS_incr(H5F_t *f, H5FS_t *fspace); +H5_DLL herr_t H5FS_decr(H5F_t *f, H5FS_t *fspace); +H5_DLL herr_t H5FS_dirty(H5F_t *f, H5FS_t *fspace); /* Free space section routines */ H5_DLL H5FS_sinfo_t *H5FS_sinfo_new(H5F_t *f, H5FS_t *fspace); @@ -211,5 +230,11 @@ H5_DLL herr_t H5FS_assert(const H5FS_t *fspace); H5_DLL herr_t H5FS_sect_assert(const H5FS_t *fspace); #endif /* H5FS_DEBUG */ +/* Testing routines */ +#ifdef H5FS_TESTING +H5_DLL herr_t H5FS_get_cparam_test(const H5FS_t *fh, H5FS_create_t *cparam); +H5_DLL int H5FS_cmp_cparam_test(const H5FS_create_t *cparam1, const H5FS_create_t *cparam2); +#endif /* H5FS_TESTING */ + #endif /* _H5FSpkg_H */ diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h index ff8ecfd..6f73b93 100644 --- a/src/H5FSprivate.h +++ b/src/H5FSprivate.h @@ -43,10 +43,14 @@ * serialized to the file. */ #define H5FS_CLS_SEPAR_OBJ 0x02 /* Objects in this class shouldn't - * participate in merge operations + * participate in merge operations. */ #define H5FS_CLS_MERGE_SYM 0x04 /* Objects in this class only merge - * with other objects in this class + * with other objects in this class. + */ +#define H5FS_CLS_ADJUST_OK 0x08 /* Objects in this class can be merged + * without requiring a can_adjust/adjust + * callback pair. */ /* Flags for H5FS_add() */ @@ -103,6 +107,7 @@ typedef struct H5FS_section_class_t { herr_t (*shrink)(H5FS_section_info_t **, void *); /* Routine to shrink container */ herr_t (*free)(H5FS_section_info_t *); /* Routine to free node */ herr_t (*valid)(const struct H5FS_section_class_t *, const H5FS_section_info_t *); /* Routine to check if a section is valid */ + H5FS_section_info_t *(*split)(H5FS_section_info_t *, hsize_t); /* Routine to create the split section */ herr_t (*debug)(const H5FS_section_info_t *, FILE *, int , int ); /* Routine to dump debugging information about a section */ } H5FS_section_class_t; @@ -123,6 +128,7 @@ struct H5FS_section_info_t { /* Free space client IDs for identifying user of free space */ typedef enum H5FS_client_t { H5FS_CLIENT_FHEAP_ID = 0, /* Free space is used by fractal heap */ + H5FS_CLIENT_FILE_ID, /* Free space is used by file */ H5FS_NUM_CLIENT_ID /* Number of free space client IDs (must be last) */ } H5FS_client_t; @@ -135,6 +141,15 @@ typedef struct H5FS_create_t { hsize_t max_sect_size; /* Maximum size of section to track */ } H5FS_create_t; +/* Free space statistics info */ +typedef struct H5FS_stat_t { + hsize_t tot_space; /* Total amount of space tracked */ + hsize_t tot_sect_count; /* Total # of sections tracked */ + hsize_t serial_sect_count; /* # of serializable sections tracked */ + hsize_t ghost_sect_count; /* # of un-serializable sections tracked */ +} H5FS_stat_t; + + /* Typedef for iteration operations */ typedef herr_t (*H5FS_operator_t)(const H5FS_section_info_t *sect, void *operator_data/*in,out*/); @@ -155,9 +170,9 @@ H5FL_SEQ_EXTERN(H5FS_section_class_t); /* Free space manager routines */ H5_DLL H5FS_t *H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_create, size_t nclasses, - const H5FS_section_class_t *classes[], void *cls_init_udata); + const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold); H5_DLL H5FS_t *H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, - size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata); + size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold); H5_DLL herr_t H5FS_size(const H5F_t *f, const H5FS_t *fspace, hsize_t *meta_size); H5_DLL herr_t H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr); H5_DLL herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); @@ -165,15 +180,22 @@ H5_DLL herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); /* Free space section routines */ H5_DLL herr_t H5FS_sect_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *node, unsigned flags, void *op_data); +H5_DLL herr_t H5FS_sect_try_extend(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, + haddr_t addr, hsize_t size, hsize_t extra_requested); H5_DLL herr_t H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *node); H5_DLL htri_t H5FS_sect_find(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node); H5_DLL herr_t H5FS_sect_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, void *op_data); -H5_DLL herr_t H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects); +H5_DLL herr_t H5FS_sect_stats(const H5FS_t *fspace, hsize_t *tot_space, + hsize_t *nsects); H5_DLL herr_t H5FS_sect_change_class(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect, unsigned new_class); +/* Statistics routine */ +H5_DLL herr_t H5FS_stat_info(const H5FS_t *fh, H5FS_stat_t *stats); + + /* Debugging routines for dumping file structures */ H5_DLL herr_t H5FS_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth); diff --git a/src/H5FSsection.c b/src/H5FSsection.c index 6aad881..42c0f86 100644 --- a/src/H5FSsection.c +++ b/src/H5FSsection.c @@ -40,6 +40,8 @@ /* Local Macros */ /****************/ +/* #define QAK */ + /* Default starting size of section buffer */ #define H5FS_SINFO_SIZE_DEFAULT 64 @@ -67,27 +69,26 @@ typedef struct { /********************/ /* Local Prototypes */ /********************/ -static herr_t H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, - const H5FS_section_class_t *cls, unsigned flags); -static herr_t H5FS_sect_decrease(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, - const H5FS_section_class_t *cls); +static herr_t H5FS_sect_increase(H5FS_t *fspace, const H5FS_section_class_t *cls, + unsigned flags); +static herr_t H5FS_sect_decrease(H5FS_t *fspace, const H5FS_section_class_t *cls); static herr_t H5FS_size_node_decr(H5FS_sinfo_t *sinfo, unsigned bin, H5FS_node_t *fspace_node, const H5FS_section_class_t *cls); static herr_t H5FS_sect_unlink_size(H5FS_sinfo_t *sinfo, const H5FS_section_class_t *cls, H5FS_section_info_t *sect); -static herr_t H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, +static herr_t H5FS_sect_unlink_rest(H5FS_t *fspace, const H5FS_section_class_t *cls, H5FS_section_info_t *sect); +static herr_t H5FS_sect_remove_real(H5FS_t *fspace, H5FS_section_info_t *sect); static herr_t H5FS_sect_link_size(H5FS_sinfo_t *sinfo, const H5FS_section_class_t *cls, H5FS_section_info_t *sect); -static herr_t H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, - const H5FS_section_class_t *cls, H5FS_section_info_t *sect, unsigned flags); -static herr_t H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, +static herr_t H5FS_sect_link_rest(H5FS_t *fspace, const H5FS_section_class_t *cls, H5FS_section_info_t *sect, unsigned flags); -static herr_t H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, - H5FS_section_info_t **sect, void *op_data); +static herr_t H5FS_sect_link(H5FS_t *fspace, H5FS_section_info_t *sect, + unsigned flags); +static herr_t H5FS_sect_merge(H5FS_t *fspace, H5FS_section_info_t **sect, + void *op_data); static htri_t H5FS_sect_find_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node); -static herr_t H5FS_sect_serialize_size(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); - +static herr_t H5FS_sect_serialize_size(H5FS_t *fspace); /*********************/ /* Package Variables */ @@ -138,6 +139,9 @@ H5FS_sinfo_new(H5F_t *f, H5FS_t *fspace) /* Check arguments. */ HDassert(f); HDassert(fspace); +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: fspace->addr = %a\n", FUNC, fspace->addr); +#endif /* H5FS_SINFO_DEBUG */ /* Allocate the free space header */ if(NULL == (sinfo = H5FL_CALLOC(H5FS_sinfo_t))) @@ -148,113 +152,370 @@ H5FS_sinfo_new(H5F_t *f, H5FS_t *fspace) sinfo->sect_prefix_size = H5FS_SINFO_PREFIX_SIZE(f); sinfo->sect_off_size = (fspace->max_sect_addr + 7) / 8; sinfo->sect_len_size = H5V_limit_enc_size((uint64_t)fspace->max_sect_size); - sinfo->fspace = fspace; -#ifdef QAK +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: fspace->max_sect_size = %Hu\n", FUNC, fspace->max_sect_size); +HDfprintf(stderr, "%s: fspace->max_sect_addr = %u\n", FUNC, fspace->max_sect_addr); HDfprintf(stderr, "%s: sinfo->nbins = %u\n", FUNC, sinfo->nbins); HDfprintf(stderr, "%s: sinfo->sect_off_size = %u, sinfo->sect_len_size = %u\n", FUNC, sinfo->sect_off_size, sinfo->sect_len_size); -#endif /* QAK */ +#endif /* H5FS_SINFO_DEBUG */ /* Allocate space for the section size bins */ if(NULL == (sinfo->bins = H5FL_SEQ_CALLOC(H5FS_bin_t, (size_t)sinfo->nbins))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space section bin array") + /* Increment the reference count on the free space manager header */ + if(H5FS_incr(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINC, NULL, "unable to increment ref. count on free space header") + sinfo->fspace = fspace; + + /* Link free space manager to section info */ + /* (for deserializing sections) */ + HDassert(fspace->sinfo == NULL); + fspace->sinfo = sinfo; + /* Set return value */ ret_value = sinfo; done: + if(ret_value == NULL && sinfo) { + /* Release bins for skip lists */ + if(sinfo->bins) + sinfo->bins = H5FL_SEQ_FREE(H5FS_bin_t, sinfo->bins); + /* Release free space section info */ + H5FL_FREE(H5FS_sinfo_t, sinfo); + } /* end if */ + FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sinfo_new() */ /*------------------------------------------------------------------------- - * Function: H5FS_sinfo_pin + * Function: H5FS_sinfo_lock * - * Purpose: Pin the section info for the free space manager in memory - * Either loads section info from disk, or creates new section info + * Purpose: Make certain the section info for the free space manager is + * in memory. * - * Return: Success: non-NULL, pointer to section info struct - * Failure: NULL + * Either uses existing section info owned by the free space + * header, loads section info from disk, or creates new section + * info + * + * Return: Success: non-negative + * Failure: negative * * Programmer: Quincey Koziol - * Monday, July 31, 2006 + * Thursday, February 7, 2008 * *------------------------------------------------------------------------- */ -static H5FS_sinfo_t * -H5FS_sinfo_pin(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) +static herr_t +H5FS_sinfo_lock(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5AC_protect_t accmode) { - H5FS_sinfo_t *sinfo; /* Section information struct created */ - H5FS_sinfo_t *ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* 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 */ + FUNC_ENTER_NOAPI_NOINIT(H5FS_sinfo_lock) +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: Called, fspace->addr = %a, fspace->sinfo = %p, fspace->sect_addr = %a\n", FUNC, fspace->addr, fspace->sinfo, fspace->sect_addr); +HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size); +#endif /* H5FS_SINFO_DEBUG */ /* Check arguments. */ HDassert(f); HDassert(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); - HDassert(fspace->ghost_sect_count == 0); + /* If the free space header doesn't already "own" the section info, load + * section info or create it + */ + if(fspace->sinfo) { + /* Check if the section info was protected & we want a different access mode */ + if(fspace->sinfo_protected && accmode != fspace->sinfo_accmode) { + /* Check if we need to switch from read-only access to read-write */ + if(H5AC_WRITE == accmode) { + /* Unprotect the read-only section info */ + if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space section info") + + /* Re-protect the section info with read-write access */ + if(NULL == (fspace->sinfo = H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, NULL, fspace, H5AC_WRITE))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to load free space sections") + + /* Switch the access mode we have */ + fspace->sinfo_accmode = H5AC_WRITE; + } /* end if */ + } /* end if */ + } /* end if */ + else { + /* If the section address is defined, load it from the file */ + if(H5F_addr_defined(fspace->sect_addr)) { + /* Sanity check */ + HDassert(fspace->sinfo_protected == FALSE); + HDassert(H5F_addr_defined(fspace->addr)); - /* Allocate and initialize free space section info */ - if(NULL == (sinfo = H5FS_sinfo_new(f, fspace))) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, NULL, "can't create section info") +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: Reading in existing sections, fspace->sect_addr = %a\n", FUNC, fspace->sect_addr); +#endif /* H5FS_SINFO_DEBUG */ + /* Protect the free space sections */ + if(NULL == (fspace->sinfo = H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, NULL, fspace, accmode))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to load free space sections") + + /* Remember that we protected the section info & the access mode */ + fspace->sinfo_protected = TRUE; + fspace->sinfo_accmode = accmode; + } /* end if */ + else { +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: Creating new section info\n", FUNC); +#endif /* H5FS_SINFO_DEBUG */ + /* Sanity check */ + HDassert(fspace->tot_sect_count == 0); + HDassert(fspace->serial_sect_count == 0); + HDassert(fspace->ghost_sect_count == 0); + + /* Allocate and initialize free space section info */ + if(NULL == (fspace->sinfo = H5FS_sinfo_new(f, fspace))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create section info") + + /* Set initial size of section info to 0 */ + fspace->sect_size = fspace->alloc_sect_size = 0; + } /* end if */ + } /* end if */ + HDassert(fspace->rc == 2); - /* Allocate space for the section info */ - fspace->sect_size = H5FS_SINFO_SIZE_DEFAULT; - 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 */ + /* Increment the section info lock count */ + fspace->sinfo_lock_count++; + +done: +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: Leaving, fspace->addr = %a, fspace->sinfo = %p, fspace->sect_addr = %a\n", FUNC, fspace->addr, fspace->sinfo, fspace->sect_addr); +HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size); +#endif /* H5FS_SINFO_DEBUG */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_sinfo_lock() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_sinfo_unlock + * + * Purpose: Release the section info, either giving ownership back to + * the cache or letting the free space header keep it. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Thursday, February 7, 2008 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_sinfo_unlock(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, hbool_t modified) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_sinfo_unlock) +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: Called, modified = %t, fspace->addr = %a, fspace->sect_addr = %a\n", FUNC, modified, fspace->addr, fspace->sect_addr); +HDfprintf(stderr, "%s: fspace->sinfo_lock_count = %u, fspace->sinfo_modified = %t, fspace->sinfo_protected = %t\n", FUNC, fspace->sinfo_lock_count, fspace->sinfo_modified, fspace->sinfo_protected); +HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size); +#endif /* H5FS_SINFO_DEBUG */ + + /* Check arguments. */ + HDassert(f); + HDassert(fspace); + HDassert(fspace->rc == 2); + HDassert(fspace->sinfo); + + /* Check if we modified any section */ + if(modified) { + /* Check if the section info was protected with a different access mode */ + if(fspace->sinfo_protected && fspace->sinfo_accmode != H5AC_WRITE) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDIRTY, FAIL, "attempt to modify read-only section info") - /* 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) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space sections to cache") + /* If we modified the section info, mark it dirty */ + fspace->sinfo->dirty = TRUE; - /* Mark free space header as dirty */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, NULL, "unable to mark free space header as dirty") + /* Remember that the section info was modified while locked */ + fspace->sinfo_modified = TRUE; + + /* Assume that the modification will affect the statistics in the header + * and mark that dirty also + */ + if(H5FS_dirty(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") } /* end if */ - else { + + /* Decrement the lock count on the section info */ + fspace->sinfo_lock_count--; + + /* Check if section info lock count dropped to zero */ + if(fspace->sinfo_lock_count == 0) { + hbool_t release_sinfo_space = FALSE; /* Flag to indicate section info space in file should be released */ + + /* Check if we actually protected the section info */ + if(fspace->sinfo_protected) { + unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap */ + + /* Sanity check */ + HDassert(H5F_addr_defined(fspace->addr)); + + /* Check if we've made new changes to the section info while locked */ + if(fspace->sinfo_modified) { + /* Note that we've modified the section info */ + cache_flags |= H5AC__DIRTIED_FLAG; + + /* Check if the section info size in the file has changed */ + if(fspace->sect_size != fspace->alloc_sect_size) + cache_flags |= H5AC__SIZE_CHANGED_FLAG | H5AC__DELETED_FLAG | H5AC__TAKE_OWNERSHIP_FLAG; + } /* end if */ + + /* Sanity check */ + HDassert(H5F_addr_defined(fspace->sect_addr)); + + /* Unprotect section info in cache */ + /* (Possibly dirty) */ + /* (Possibly taking ownership from the cache) */ +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: Unprotecting section info, cache_flags = %u\n", FUNC, cache_flags); +#endif /* H5FS_SINFO_DEBUG */ + if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, cache_flags) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space section info") + + /* Reset the protected flag on the section info */ + fspace->sinfo_protected = FALSE; + + /* Check if header is taking ownership of section info */ + if((cache_flags & H5AC__TAKE_OWNERSHIP_FLAG)) { +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: Taking ownership of section info\n", FUNC); +#endif /* H5FS_SINFO_DEBUG */ + /* Set flag to release section info space in file */ + release_sinfo_space = TRUE; + } /* end if */ + else { +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: Relinquishing section info ownership\n", FUNC); +#endif /* H5FS_SINFO_DEBUG */ + /* Free space header relinquished ownership of section info */ + fspace->sinfo = NULL; + } /* end else */ + } /* end if */ + else { + /* Check if the section info was modified */ + if(fspace->sinfo_modified) { + /* Check if we need to release section info in the file */ + if(H5F_addr_defined(fspace->sect_addr)) + /* Set flag to release section info space in file */ + release_sinfo_space = TRUE; + else + HDassert(fspace->alloc_sect_size == 0); + } /* end if */ + else { + /* Sanity checks... */ + if(H5F_addr_defined(fspace->sect_addr)) + HDassert(fspace->alloc_sect_size == fspace->sect_size); + else + HDassert(fspace->alloc_sect_size == 0); + } /* end else */ + } /* end else */ + + /* Reset the "section info modified" flag */ + fspace->sinfo_modified = FALSE; + + /* Check if header needs to release section info in the file */ + if(release_sinfo_space) { + haddr_t old_sect_addr = fspace->sect_addr; /* Previous location of section info in file */ + hsize_t old_alloc_sect_size = fspace->alloc_sect_size; /* Previous size of section info in file */ + + /* Sanity check */ + HDassert(H5F_addr_defined(fspace->addr)); + + /* Reset section info in header */ + fspace->sect_addr = HADDR_UNDEF; + fspace->alloc_sect_size = 0; + + /* If we haven't already marked the header dirty, do so now */ + if(!modified) + if(H5FS_dirty(f, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") + +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: Freeing section info on disk, old_sect_addr = %a, old_alloc_sect_size = %Hu\n", FUNC, old_sect_addr, old_alloc_sect_size); +#endif /* H5FS_SINFO_DEBUG */ + /* Release space for section info in file */ + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_sect_addr, old_alloc_sect_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections") + } /* end if */ + } /* end if */ + +done: +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value); +#endif /* H5FS_SINFO_DEBUG */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_sinfo_unlock() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_sect_serialize_size + * + * Purpose: Determine serialized size of all sections in free space manager + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_sect_serialize_size(H5FS_t *fspace) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_serialize_size) + + /* Check arguments. */ + HDassert(fspace); #ifdef QAK -HDfprintf(stderr, "%s: Reading in existing sections, fspace->sect_addr = %a\n", FUNC, fspace->sect_addr); +HDfprintf(stderr, "%s: Check 1.0 - fspace->sect_size = %Hu\n", "H5FS_sect_serialize_size", fspace->sect_size); +HDfprintf(stderr, "%s: fspace->serial_sect_count = %Zu\n", "H5FS_sect_serialize_size", fspace->serial_sect_count); +HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", "H5FS_sect_serialize_size", fspace->alloc_sect_size); +HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", "H5FS_sect_serialize_size", fspace->sinfo->serial_size_count); #endif /* QAK */ - /* Protect the free space sections */ - if(NULL == (sinfo = (H5FS_sinfo_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, NULL, fspace, H5AC_WRITE))) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, NULL, "unable to load free space sections") - /* Pin them in the cache */ - if(H5AC_pin_protected_entry(f, sinfo) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, NULL, "unable to pin free space sections") + /* Compute the size of the buffer required to serialize all the sections */ + if(fspace->serial_sect_count > 0) { + size_t sect_buf_size; /* Section buffer size */ - /* Unlock free space sections, now pinned */ - if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, sinfo, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, NULL, "unable to release free space sections") - } /* end else */ + /* Serialized sections prefix */ + sect_buf_size = fspace->sinfo->sect_prefix_size; + + /* Count for each differently sized serializable section */ #ifdef QAK -HDfprintf(stderr, "%s: sinfo->serial_size_count = %Zu\n", FUNC, sinfo->serial_size_count); +HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", "H5FS_sect_serialize_size", fspace->sinfo->serial_size_count); +HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", "H5FS_sect_serialize_size", fspace->serial_sect_count); #endif /* QAK */ + sect_buf_size += fspace->sinfo->serial_size_count * H5V_limit_enc_size((uint64_t)fspace->serial_sect_count); - /* Update pointer to free space header for section info */ - sinfo->fspace = fspace; + /* Size for each differently sized serializable section */ + sect_buf_size += fspace->sinfo->serial_size_count * fspace->sinfo->sect_len_size; - /* Set return value */ - ret_value = sinfo; + /* Offsets of each section in address space */ + sect_buf_size += fspace->serial_sect_count * fspace->sinfo->sect_off_size; -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FS_sinfo_pin() */ + /* Class of each section */ + sect_buf_size += fspace->serial_sect_count * 1 /* byte */; + + /* Extra space required to serialize each section */ + sect_buf_size += fspace->sinfo->serial_size; + + /* Update section size in header */ + fspace->sect_size = sect_buf_size; + } /* end if */ + else + /* Reset section size in header */ + fspace->sect_size = fspace->sinfo->sect_prefix_size; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5FS_sect_serialize_size() */ /*------------------------------------------------------------------------- @@ -264,7 +525,6 @@ done: * on disk * * Return: Success: non-negative - * * Failure: negative * * Programmer: Quincey Koziol @@ -273,8 +533,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, - const H5FS_section_class_t *cls, unsigned flags) +H5FS_sect_increase(H5FS_t *fspace, const H5FS_section_class_t *cls, + unsigned flags) { herr_t ret_value = SUCCEED; /* Return value */ @@ -310,15 +570,11 @@ HDfprintf(stderr, "%s: cls->serial_size = %Zu\n", FUNC, cls->serial_size); /* Update the free space sections' serialized size */ /* (if we're not deserializing the sections from disk) */ if(!(flags & H5FS_ADD_DESERIALIZING)) { - if(H5FS_sect_serialize_size(f, dxpl_id, fspace) < 0) + if(H5FS_sect_serialize_size(fspace) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTCOMPUTE, FAIL, "can't adjust free space section size on disk") } /* end if */ } /* end else */ - /* Mark free space header as dirty */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") - done: FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_increase() */ @@ -340,7 +596,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_decrease(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_class_t *cls) +H5FS_sect_decrease(H5FS_t *fspace, const H5FS_section_class_t *cls) { herr_t ret_value = SUCCEED; /* Return value */ @@ -374,14 +630,10 @@ HDfprintf(stderr, "%s: cls->serial_size = %Zu\n", FUNC, cls->serial_size); fspace->sinfo->serial_size -= cls->serial_size; /* Update the free space sections' serialized size */ - if(H5FS_sect_serialize_size(f, dxpl_id, fspace) < 0) + if(H5FS_sect_serialize_size(fspace) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTCOMPUTE, FAIL, "can't adjust free space section size on disk") } /* end else */ - /* Mark free space header as dirty */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") - done: FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_decrease() */ @@ -547,15 +799,14 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, - const H5FS_section_class_t *cls, H5FS_section_info_t *sect) +H5FS_sect_unlink_rest(H5FS_t *fspace, const H5FS_section_class_t *cls, + H5FS_section_info_t *sect) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_unlink_rest) /* Check arguments. */ - HDassert(f); HDassert(fspace); HDassert(fspace->sinfo); HDassert(cls); @@ -574,7 +825,7 @@ HDfprintf(stderr, "%s: removing object from merge list, sect->type = %u\n", FUNC } /* end if */ /* Update section info & check if we need less room for the serialized free space sections */ - if(H5FS_sect_decrease(f, dxpl_id, fspace, cls) < 0) + if(H5FS_sect_decrease(fspace, cls) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk") /* Decrement amount of free space managed */ @@ -583,17 +834,13 @@ HDfprintf(stderr, "%s: fspace->tot_space = %Hu\n", FUNC, fspace->tot_space); #endif /* QAK */ fspace->tot_space -= sect->size; - /* Mark free space sections as changed */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space sections as dirty") - done: FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_unlink_rest() */ /*------------------------------------------------------------------------- - * Function: H5FS_sect_remove + * Function: H5FS_sect_remove_real * * Purpose: Remove a section from the free space manager * @@ -605,17 +852,15 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, - H5FS_section_info_t *sect) +static herr_t +H5FS_sect_remove_real(H5FS_t *fspace, H5FS_section_info_t *sect) { const H5FS_section_class_t *cls; /* Class of section */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_remove) + FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_remove_real) /* Check arguments. */ - HDassert(f); HDassert(fspace); HDassert(fspace->sinfo); HDassert(sect); @@ -628,11 +873,56 @@ H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from size tracking data structures") /* Update rest of free space manager data structures for node removal */ - if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, cls, sect) < 0) + if(H5FS_sect_unlink_rest(fspace, cls, sect) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures") done: FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_sect_remove_real() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_sect_remove + * + * Purpose: Remove a section from the free space manager + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Wednesday, May 17, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, + H5FS_section_info_t *sect) +{ + hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_remove) + + /* Check arguments. */ + HDassert(f); + HDassert(fspace); + HDassert(sect); + + /* Get a pointer to the section info */ + if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info") + sinfo_valid = TRUE; + + /* Perform actual section removal */ + if(H5FS_sect_remove_real(fspace, sect) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove section") + +done: + /* Release the section info */ + if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, TRUE) < 0) + HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info") + + FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_remove() */ @@ -750,7 +1040,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_class_t *cls, +H5FS_sect_link_rest(H5FS_t *fspace, const H5FS_section_class_t *cls, H5FS_section_info_t *sect, unsigned flags) { herr_t ret_value = SUCCEED; /* Return value */ @@ -758,7 +1048,6 @@ H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_link_rest) /* Check arguments. */ - HDassert(f); HDassert(fspace); HDassert(fspace->sinfo); HDassert(sect); @@ -776,7 +1065,7 @@ HDfprintf(stderr, "%s: inserting object into merge list, sect->type = %u\n", FUN } /* end if */ /* Update section info & check if we need more room for the serialized free space sections */ - if(H5FS_sect_increase(f, dxpl_id, fspace, cls, flags) < 0) + if(H5FS_sect_increase(fspace, cls, flags) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk") /* Increment amount of free space managed */ @@ -802,8 +1091,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, - H5FS_section_info_t *sect, unsigned flags) +H5FS_sect_link(H5FS_t *fspace, H5FS_section_info_t *sect, unsigned flags) { const H5FS_section_class_t *cls; /* Class of section */ herr_t ret_value = SUCCEED; /* Return value */ @@ -811,7 +1099,6 @@ H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_link) /* Check arguments. */ - HDassert(f); HDassert(fspace); HDassert(fspace->sinfo); HDassert(sect); @@ -830,7 +1117,7 @@ HDfprintf(stderr, "%s: Check 1.0 - fspace->tot_space = %Hu\n", FUNC, fspace->tot HDfprintf(stderr, "%s: Check 2.0 - fspace->tot_space = %Hu\n", FUNC, fspace->tot_space); #endif /* QAK */ /* Update rest of free space manager data structures for section addition */ - if(H5FS_sect_link_rest(f, dxpl_id, fspace, cls, sect, flags) < 0) + if(H5FS_sect_link_rest(fspace, cls, sect, flags) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to non-size tracking data structures") #ifdef QAK HDfprintf(stderr, "%s: Check 3.0 - fspace->tot_space = %Hu\n", FUNC, fspace->tot_space); @@ -841,6 +1128,7 @@ done: } /* H5FS_sect_link() */ + /*------------------------------------------------------------------------- * Function: H5FS_sect_merge * @@ -848,21 +1136,26 @@ done: * free space. * * Return: Success: non-negative - * * Failure: negative * * Programmer: Quincey Koziol * Wednesday, May 17, 2006 * + * Modifications: Vailin Choi; Sept 25th 2008 + * Changes to the "shrinking" part-- + * 1. Get last section node in merge-list instead of "less-than" + * node for further iteration + * 2. Remove "can-be-shrunk" section from free-space instead of + * "less-than" section + * *------------------------------------------------------------------------- */ static herr_t -H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, - H5FS_section_info_t **sect, void *op_data) +H5FS_sect_merge(H5FS_t *fspace, H5FS_section_info_t **sect, void *op_data) { H5FS_section_class_t *sect_cls; /* Section's class */ - H5FS_section_info_t *tmp_sect_node; /* Temporary free space section */ hbool_t modified; /* Flag to indicate merge or shrink occurred */ + hbool_t remove_sect = FALSE; /* Whether a section should be removed before shrinking */ htri_t status; /* Status value */ herr_t ret_value = SUCCEED; /* Return value */ @@ -877,43 +1170,54 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, /* Loop until no more merging */ if(fspace->sinfo->merge_list) { do { + H5SL_node_t *less_sect_node; /* Skip list node for section less than new section */ + H5SL_node_t *greater_sect_node; /* Skip list node for section greater than new section */ + H5FS_section_info_t *tmp_sect; /* Temporary free space section */ H5FS_section_class_t *tmp_sect_cls; /* Temporary section's class */ + hbool_t greater_sect_node_valid = FALSE; /* Indicate if 'greater than' section node is valid */ /* Reset 'modification occurred' flag */ modified = FALSE; /* Look for neighboring section before new section */ - tmp_sect_node = (H5FS_section_info_t *)H5SL_less(fspace->sinfo->merge_list, &(*sect)->addr); + less_sect_node = H5SL_below(fspace->sinfo->merge_list, &(*sect)->addr); /* Check for node before new node able to merge with new node */ - if(tmp_sect_node) { + if(less_sect_node) { + /* Check for node greater than section */ + greater_sect_node = H5SL_next(less_sect_node); + greater_sect_node_valid = TRUE; + + /* Get section for 'less than' skip list node */ + tmp_sect = H5SL_item(less_sect_node); + /* Get classes for right & left sections */ - tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type]; + tmp_sect_cls = &fspace->sect_cls[tmp_sect->type]; sect_cls = &fspace->sect_cls[(*sect)->type]; /* Check if sections of the left most class can merge with sections * of another class & whether the sections are the same type, * then check for 'can merge' callback */ - if((!(tmp_sect_cls->flags & H5FS_CLS_MERGE_SYM) || (tmp_sect_node->type == (*sect)->type)) + if((!(tmp_sect_cls->flags & H5FS_CLS_MERGE_SYM) || (tmp_sect->type == (*sect)->type)) && tmp_sect_cls->can_merge) { /* Determine if the sections can merge */ - if((status = (*tmp_sect_cls->can_merge)(tmp_sect_node, *sect, op_data)) < 0) + if((status = (*tmp_sect_cls->can_merge)(tmp_sect, *sect, op_data)) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections") if(status > 0) { /* Sanity check */ HDassert(tmp_sect_cls->merge); /* Remove 'less than' node from data structures */ - if(H5FS_sect_remove(f, dxpl_id, fspace, tmp_sect_node) < 0) + if(H5FS_sect_remove_real(fspace, tmp_sect) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") /* Merge the two sections together */ - if((*tmp_sect_cls->merge)(tmp_sect_node, *sect, op_data) < 0) + if((*tmp_sect_cls->merge)(tmp_sect, *sect, op_data) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") /* Retarget section pointer to 'less than' node that was merged into */ - *sect = tmp_sect_node; + *sect = tmp_sect; /* Indicate successful merge occurred */ modified = TRUE; @@ -921,35 +1225,39 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, } /* end if */ } /* end if */ - /* Look for section after new (or merged) section */ - tmp_sect_node = (H5FS_section_info_t *)H5SL_greater(fspace->sinfo->merge_list, &(*sect)->addr); + /* Look for section after new (or merged) section, if not already determined */ + if(!greater_sect_node_valid) + greater_sect_node = H5SL_above(fspace->sinfo->merge_list, &(*sect)->addr); /* Check for node after new node able to merge with new node */ - if(tmp_sect_node) { + if(greater_sect_node) { + /* Get section for 'greater than' skip list node */ + tmp_sect = H5SL_item(greater_sect_node); + /* Get classes for right & left sections */ sect_cls = &fspace->sect_cls[(*sect)->type]; - tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type]; + tmp_sect_cls = &fspace->sect_cls[tmp_sect->type]; /* Check if sections of the left most class can merge with sections * of another class & whether the sections are the same type, * then check for 'can merge' callback */ - if((!(sect_cls->flags & H5FS_CLS_MERGE_SYM) || ((*sect)->type == tmp_sect_node->type)) + if((!(sect_cls->flags & H5FS_CLS_MERGE_SYM) || ((*sect)->type == tmp_sect->type)) && sect_cls->can_merge) { /* Determine if the sections can merge */ - if((status = (*sect_cls->can_merge)(*sect, tmp_sect_node, op_data)) < 0) + if((status = (*sect_cls->can_merge)(*sect, tmp_sect, op_data)) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections") if(status > 0) { /* Sanity check */ HDassert(sect_cls->merge); /* Remove 'greater than' node from data structures */ - if(H5FS_sect_remove(f, dxpl_id, fspace, tmp_sect_node) < 0) + if(H5FS_sect_remove_real(fspace, tmp_sect) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") /* Merge the two sections together */ - if((*sect_cls->merge)(*sect, tmp_sect_node, op_data) < 0) + if((*sect_cls->merge)(*sect, tmp_sect, op_data) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections") /* Indicate successful merge occurred */ @@ -957,7 +1265,7 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, } /* end if */ } /* end if */ } /* end if */ - } while(modified); + } while(modified); } /* end if */ HDassert(*sect); #ifdef QAK @@ -978,15 +1286,14 @@ HDfprintf(stderr, "%s: Done merging, (*sect) = {%a, %Hu, %u, %s}\n", FUNC, (*sec #ifdef QAK HDfprintf(stderr, "%s: Can shrink!\n", FUNC); #endif /* QAK */ - /* Look for neighboring section before new section */ - if(fspace->sinfo->merge_list) { - tmp_sect_node = (H5FS_section_info_t *)H5SL_less(fspace->sinfo->merge_list, &(*sect)->addr); - /* Make certain there isn't a section after the new section */ - HDassert(H5SL_greater(fspace->sinfo->merge_list, &(*sect)->addr) == NULL); - } /* end if */ - else - tmp_sect_node = NULL; + /* Remove SECT from free-space manager */ + /* (only possible to happen on second+ pass through loop) */ + if(remove_sect) { + if(H5FS_sect_remove_real(fspace, *sect) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") + remove_sect = FALSE; + } /* end if */ /* Shrink the container */ /* (callback can indicate that it has discarded the section by setting *sect to NULL) */ @@ -994,20 +1301,34 @@ HDfprintf(stderr, "%s: Can shrink!\n", FUNC); if((*sect_cls->shrink)(sect, op_data) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't shrink free space container") - /* Check if the new section was removed */ - if(*sect == NULL && tmp_sect_node) { - /* Remove 'less than' node from data structures */ - if(H5FS_sect_remove(f, dxpl_id, fspace, tmp_sect_node) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") - - *sect = tmp_sect_node; - } /* end if */ + /* If this section was shrunk away, we may need to shrink another section */ + if(*sect == NULL) { + /* Check for sections on merge list */ + if(fspace->sinfo->merge_list) { + H5SL_node_t *last_node; /* Last node in merge list */ + + /* Check for last node in the merge list */ + if(NULL != (last_node = H5SL_last(fspace->sinfo->merge_list))) { + /* Get the pointer to the last section, from the last node */ + *sect = H5SL_item(last_node); + HDassert(*sect); + + /* Indicate that this section needs to be removed if it causes a shrink */ + remove_sect = TRUE; + } /* end if */ + } /* end if */ + } /* end if */ /* Indicate successful merge occurred */ modified = TRUE; } /* end if */ } /* end if */ } while(modified && *sect); + + /* Check for section that was shrunk away and next section not shrinking */ + if(remove_sect && (*sect != NULL)) + *sect = NULL; + #ifdef QAK HDfprintf(stderr, "%s: Done shrinking\n", FUNC); if(*sect) @@ -1043,13 +1364,15 @@ H5FS_sect_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect unsigned flags, void *op_data) { H5FS_section_class_t *cls; /* Section's class */ + hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */ + hbool_t sinfo_modified = FALSE; /* Whether the section info was modified */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FS_sect_add, FAIL) -#ifdef QAK +#ifdef H5FS_SINFO_DEBUG HDfprintf(stderr, "%s: *sect = {%a, %Hu, %u, %s}\n", FUNC, sect->addr, sect->size, sect->type, (sect->state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); -#endif /* QAK */ +#endif /* H5FS_SINFO_DEBUG */ /* Check arguments. */ HDassert(fspace); @@ -1057,11 +1380,10 @@ HDfprintf(stderr, "%s: *sect = {%a, %Hu, %u, %s}\n", FUNC, sect->addr, sect->siz HDassert(H5F_addr_defined(sect->addr)); HDassert(sect->size); - /* 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 */ + /* Get a pointer to the section info */ + if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info") + sinfo_valid = TRUE; /* Call "add" section class callback, if there is one */ cls = &fspace->sect_cls[sect->type]; @@ -1072,12 +1394,12 @@ HDfprintf(stderr, "%s: *sect = {%a, %Hu, %u, %s}\n", FUNC, sect->addr, sect->siz /* Check for merging returned space with existing section node */ if(flags & H5FS_ADD_RETURNED_SPACE) { -#ifdef QAK +#ifdef H5FS_SINFO_DEBUG HDfprintf(stderr, "%s: Returning space\n", FUNC); -#endif /* QAK */ +#endif /* H5FS_SINFO_DEBUG */ /* Attempt to merge returned section with existing sections */ - if(H5FS_sect_merge(f, dxpl_id, fspace, §, op_data) < 0) + if(H5FS_sect_merge(fspace, §, op_data) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't merge sections") } /* end if */ @@ -1086,29 +1408,157 @@ HDfprintf(stderr, "%s: Returning space\n", FUNC); * be NULL at this point - QAK) */ if(sect) - if(H5FS_sect_link(f, dxpl_id, fspace, sect, flags) < 0) + if(H5FS_sect_link(fspace, sect, flags) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list") -#ifdef QAK -HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space); -#endif /* QAK */ +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: fspace->tot_space = %Hu\n", FUNC, fspace->tot_space); +#endif /* H5FS_SINFO_DEBUG */ /* Mark free space sections as changed */ /* (if adding sections while deserializing sections, don't set the flag) */ - if(!(flags & H5FS_ADD_DESERIALIZING)) { - if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space sections as dirty") - } /* end if */ + if(!(flags & H5FS_ADD_DESERIALIZING)) + sinfo_modified = TRUE; done: -#ifdef H5FS_DEBUG + /* Release the section info */ + if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, sinfo_modified) < 0) + HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info") + +#ifdef H5FS_DEBUG_ASSERT if(!(flags & (H5FS_ADD_DESERIALIZING | H5FS_ADD_SKIP_VALID))) H5FS_assert(fspace); -#endif /* H5FS_DEBUG */ +#endif /* H5FS_DEBUG_ASSERT */ +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value); +#endif /* H5FS_SINFO_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_add() */ /*------------------------------------------------------------------------- + * Function: H5FS_sect_try_extend + * + * Purpose: Try to extend a block using space from a section on the free list + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, January 8, 2008 + * + *------------------------------------------------------------------------- + */ +htri_t +H5FS_sect_try_extend(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, haddr_t addr, + hsize_t size, hsize_t extra_requested) +{ + hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */ + hbool_t sinfo_modified = FALSE; /* Whether the section info was modified */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_sect_try_extend, FAIL) + +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: addr = %a, size = %Hu, extra_requested = %hu\n", FUNC, addr, size, extra_requested); +#endif /* H5FS_SINFO_DEBUG */ + + /* Check arguments. */ + HDassert(f); + HDassert(fspace); + HDassert(H5F_addr_defined(addr)); + HDassert(size > 0); + HDassert(extra_requested > 0); + + /* Check for any sections on free space list */ +#ifdef H5FS_SINFO_DEBUG +HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count); +HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", FUNC, fspace->serial_sect_count); +HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", FUNC, fspace->ghost_sect_count); +#endif /* H5FS_SINFO_DEBUG */ + if(fspace->tot_sect_count > 0) { + H5FS_section_info_t *sect; /* Temporary free space section */ + + /* Get a pointer to the section info */ + if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info") + sinfo_valid = TRUE; + + +/* + +Pseudo-code for algorithm: + +_section_ = <Get pointer to section with address > _region.addr_> +if(_section_) + if(_section_ adjoins _region_ && _section.size_ >= _extra_requested_) + <remove section from data structures> + if(_section.size_ > _extra_requested_) + if(<can adjust _section_>) + <adjust _section_ by _extra_requested_> + <add adjusted section back to data structures> + else + <re-add UNadjusted section back to data structures> + <error> + <mark free space sections as changed in metadata cache> + +*/ + /* Look for a section after block to extend */ + if((sect = H5SL_greater(fspace->sinfo->merge_list, &addr))) { + /* Check if this section adjoins the block and is large enough to + * fulfill extension request. + * + * (Note: we assume that the section is fully merged with any + * possible neighboring nodes and is not at the end of the file + * (or it would have been eliminated), etc) + */ + if(sect->size >= extra_requested && (addr + size) == sect->addr) { + /* Remove section from data structures */ + if(H5FS_sect_remove_real(fspace, sect) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures") + + /* Check for the section needing to be adjusted and re-added */ + /* (Note: we should probably add a can_adjust/adjust callback + * to the section class structure, but we don't need it + * for the current usage, so I've deferred messing with + * it. - QAK - 2008/01/08) + */ + if(sect->size > extra_requested) { + H5FS_section_class_t *cls; /* Section's class */ + + /* Get class for section */ + cls = &fspace->sect_cls[sect->type]; + + /* Sanity check (for now) */ + HDassert(cls->flags & H5FS_CLS_ADJUST_OK); + + /* Adjust section by amount requested */ + sect->addr += extra_requested; + sect->size -= extra_requested; + + /* Re-add adjusted section to free sections data structures */ + if(H5FS_sect_link(fspace, sect, 0) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list") + } /* end if */ + + /* Note that we modified the section info */ + sinfo_modified = TRUE; + + /* Indicate success */ + HGOTO_DONE(TRUE); + } /* end if */ + } /* end if */ + } /* end if */ + +done: + /* Release the section info */ + if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, sinfo_modified) < 0) + HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_sect_try_extend() */ + + +/*------------------------------------------------------------------------- * Function: H5FS_sect_find_node * * Purpose: Locate a section of free space (in existing free space list @@ -1121,6 +1571,11 @@ if(!(flags & (H5FS_ADD_DESERIALIZING | H5FS_ADD_SKIP_VALID))) * Programmer: Quincey Koziol * Monday, March 20, 2006 * + * Modifications: + * Vailin Choi, July 29th, 2008 + * Modified to handle alignment by going through each bin to find + * a section that is big enough to fulfill "request+fragment for alignment" + * *------------------------------------------------------------------------- */ static htri_t @@ -1130,6 +1585,10 @@ H5FS_sect_find_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node) unsigned bin; /* Bin to put the free space section in */ htri_t ret_value = FALSE; /* Return value */ + H5SL_node_t *curr_size_node=NULL; + const H5FS_section_class_t *cls; /* Class of section */ + hsize_t alignment; + FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_find_node) /* Check arguments. */ @@ -1142,43 +1601,113 @@ H5FS_sect_find_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node) /* Determine correct bin which holds items of at least the section's size */ bin = H5V_log2_gen(request); HDassert(bin < fspace->sinfo->nbins); - while(bin < fspace->sinfo->nbins && fspace->sinfo->bins[bin].bin_list == NULL) - bin++; - - /* Find the first free space section that is large enough to fulfill request */ - /* (Since the bins use skip lists to track the sizes of the address-ordered - * lists, this is actually a "best fit" algorithm) - */ #ifdef QAK HDfprintf(stderr, "%s: fspace->sinfo->nbins = %u\n", FUNC, fspace->sinfo->nbins); HDfprintf(stderr, "%s: bin = %u\n", FUNC, bin); #endif /* QAK */ - if(bin < fspace->sinfo->nbins) - do { - /* Look for large enough free space section in this bin */ - if(fspace->sinfo->bins[bin].bin_list) - /* Check for large enough list of sections on list */ - if((fspace_node = (H5FS_node_t *)H5SL_greater(fspace->sinfo->bins[bin].bin_list, &request))) { - const H5FS_section_class_t *cls; /* Class of section */ - - /* Take first node off of the list (ie. node w/lowest address) */ - if(NULL == (*node = (H5FS_section_info_t *)H5SL_remove_first(fspace_node->sect_list))) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list") + alignment = fspace->alignment; + if(!((alignment > 1) && (request >= fspace->threshold))) + alignment = 0; /* no alignment */ - /* Get section's class */ - cls = &fspace->sect_cls[(*node)->type]; + do { + /* Check if there's any sections in this bin */ + if(fspace->sinfo->bins[bin].bin_list) { + + if (!alignment) { /* no alignment */ + /* Find the first free space section that is large enough to fulfill request */ + /* (Since the bins use skip lists to track the sizes of the address-ordered + * lists, this is actually a "best fit" algorithm) + */ + /* Look for large enough free space section in this bin */ + if((fspace_node = (H5FS_node_t *)H5SL_greater(fspace->sinfo->bins[bin].bin_list, &request))) { + /* Take first node off of the list (ie. node w/lowest address) */ + if(NULL == (*node = (H5FS_section_info_t *)H5SL_remove_first(fspace_node->sect_list))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list") + + /* Get section's class */ + cls = &fspace->sect_cls[(*node)->type]; + /* Decrement # of sections in section size node */ + if(H5FS_size_node_decr(fspace->sinfo, bin, fspace_node, cls) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list") + if(H5FS_sect_unlink_rest(fspace, cls, *node) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures") + /* Indicate that we found a node for the request */ + HGOTO_DONE(TRUE) + } /* end if */ + } /* end if */ + else { /* alignment is set */ + /* get the first node of a certain size in this bin */ + curr_size_node = H5SL_first(fspace->sinfo->bins[bin].bin_list); + while (curr_size_node != NULL) { + H5FS_node_t *curr_fspace_node=NULL; + H5SL_node_t *curr_sect_node=NULL; + + /* Get the free space node for free space sections of the same size */ + curr_fspace_node = H5SL_item(curr_size_node); + + /* Get the Skip list which holds pointers to actual free list sections */ + curr_sect_node = H5SL_first(curr_fspace_node->sect_list); - /* Decrement # of sections in section size node */ - if(H5FS_size_node_decr(fspace->sinfo, bin, fspace_node, cls) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list") + while(curr_sect_node != NULL) { + H5FS_section_info_t *curr_sect=NULL; + hsize_t mis_align=0, frag_size=0; + H5FS_section_info_t *split_sect=NULL; + + /* Get section node */ + curr_sect = H5SL_item(curr_sect_node); + + HDassert(H5F_addr_defined(curr_sect->addr)); + HDassert(curr_fspace_node->sect_size == curr_sect->size); + + cls = &fspace->sect_cls[curr_sect->type]; + + HDassert(alignment); + HDassert(cls); + + if ((mis_align = curr_sect->addr % alignment)) + frag_size = alignment - mis_align; + + if ((curr_sect->size >= (request + frag_size)) && (cls->split)) { + /* remove the section with aligned address */ + if(NULL == (*node = H5SL_remove(curr_fspace_node->sect_list, &curr_sect->addr))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list") + /* Decrement # of sections in section size node */ + if(H5FS_size_node_decr(fspace->sinfo, bin, curr_fspace_node, cls) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list") + + if(H5FS_sect_unlink_rest(fspace, cls, *node) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures") + + /* + * The split() callback splits NODE into 2 sections: + * split_sect is the unused fragment for aligning NODE + * NODE's addr & size are updated to point to the remaining aligned section + * split_sect is re-added to free-space + */ + if (mis_align) { + split_sect = cls->split(*node, frag_size); + if((H5FS_sect_link(fspace, split_sect, 0) < 0)) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list") + /* sanity check */ + HDassert(split_sect->addr < (*node)->addr); + HDassert(request <= (*node)->size); + } + /* Indicate that we found a node for the request */ + HGOTO_DONE(TRUE) + } - /* Indicate that we found a node for the request */ - HGOTO_DONE(TRUE) - } /* end if */ + /* Get the next section node in the list */ + curr_sect_node = H5SL_next(curr_sect_node); + } /* end while of curr_sect_node */ - /* Advance to next larger bin */ - bin++; - } while(bin < fspace->sinfo->nbins); + /* Get the next size node in the bin */ + curr_size_node = H5SL_next(curr_size_node); + } /* end while of curr_size_node */ + } /* else of alignment */ + } /* if bin_list */ + /* Advance to next larger bin */ + bin++; + } while(bin < fspace->sinfo->nbins); done: FUNC_LEAVE_NOAPI(ret_value) @@ -1198,12 +1727,18 @@ done: * Programmer: Quincey Koziol * Tuesday, March 7, 2006 * + * Modifications: + * Vailin Choi, July 29th 2008 + * Move H5FS_sect_unlink_rest() to H5FS_sect_find_node() + * *------------------------------------------------------------------------- */ htri_t H5FS_sect_find(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node) { + hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */ + hbool_t sinfo_modified = FALSE; /* Whether the section info was modified */ htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI(H5FS_sect_find, FAIL) @@ -1225,11 +1760,10 @@ 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 */ + /* Get a pointer to the section info */ + if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info") + sinfo_valid = TRUE; /* Look for node in bins */ if((ret_value = H5FS_sect_find_node(fspace, request, node)) < 0) @@ -1237,209 +1771,27 @@ HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", FUNC, fspace->ghost_se /* Decrement # of sections on free list, if we found an object */ if(ret_value > 0) { - const H5FS_section_class_t *cls; /* Class of section */ - - /* Get section's class */ - cls = &fspace->sect_cls[(*node)->type]; - - /* Update rest of free space manager data structures for node removal */ - if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, cls, *node) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures") + /* Note that we've modified the section info */ + sinfo_modified = TRUE; #ifdef QAK HDfprintf(stderr, "%s: (*node)->size = %Hu, (*node)->addr = %a, (*node)->type = %u\n", FUNC, (*node)->size, (*node)->addr, (*node)->type); #endif /* QAK */ - } /* end if */ + } } /* end if */ done: -#ifdef H5FS_DEBUG + /* Release the section info */ + if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, sinfo_modified) < 0) + HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info") + +#ifdef H5FS_DEBUG_ASSERT H5FS_assert(fspace); -#endif /* H5FS_DEBUG */ +#endif /* H5FS_DEBUG_ASSERT */ FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_find() */ /*------------------------------------------------------------------------- - * Function: H5FS_sect_serialize_size - * - * Purpose: Determine serialized size of all sections in free space manager - * And adjust space on disk for storing serialized sections - * - * Return: Success: non-negative - * Failure: negative - * - * Programmer: Quincey Koziol - * Monday, May 8, 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5FS_sect_serialize_size(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_serialize_size) - - /* Check arguments. */ - HDassert(fspace); -#ifdef QAK -HDfprintf(stderr, "%s: Check 1.0 - fspace->sect_size = %Hu\n", FUNC, fspace->sect_size); -HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", FUNC, fspace->alloc_sect_size); -HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", FUNC, fspace->sinfo->serial_size_count); -#endif /* QAK */ - - /* Compute the size of the buffer required to serialize all the sections */ - if(fspace->serial_sect_count > 0) { - size_t sect_buf_size; /* Section buffer size */ - - /* Serialized sections prefix */ - sect_buf_size = fspace->sinfo->sect_prefix_size; - - /* Count for each differently sized serializable section */ -#ifdef QAK -HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", FUNC, fspace->sinfo->serial_size_count); -HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", FUNC, fspace->serial_sect_count); -#endif /* QAK */ - sect_buf_size += fspace->sinfo->serial_size_count * H5V_limit_enc_size((uint64_t)fspace->serial_sect_count); - - /* Size for each differently sized serializable section */ - sect_buf_size += fspace->sinfo->serial_size_count * fspace->sinfo->sect_len_size; - - /* Offsets of each section in address space */ - sect_buf_size += fspace->serial_sect_count * fspace->sinfo->sect_off_size; - - /* Class of each section */ - sect_buf_size += fspace->serial_sect_count * 1; - - /* Extra space required to serialize each section */ - sect_buf_size += fspace->sinfo->serial_size; - - /* Update section size in header */ - fspace->sect_size = sect_buf_size; - } /* end if */ - else - /* Reset section size in header */ - fspace->sect_size = H5FS_SINFO_SIZE_DEFAULT; - -#ifdef QAK -HDfprintf(stderr, "%s: Check 2.0 - fspace->sect_size = %Hu\n", FUNC, fspace->sect_size); -HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", FUNC, fspace->alloc_sect_size); -#endif /* QAK */ - if(fspace->sect_size > fspace->alloc_sect_size) { - size_t new_size; /* New size of space for serialized sections */ - haddr_t old_addr; /* Old address of serialized sections */ - -/* Currently, the old block 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. - * - * This also keeps the file smaller, by freeing the space and then - * allocating new space, instead of vice versa (in H5MF_realloc). - * - * QAK - 5/ 8/2006 - */ - /* Free previous serialized sections disk space */ - old_addr = fspace->sect_addr; - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_addr, fspace->alloc_sect_size) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections") - - /* Compute new size */ - H5_ASSIGN_OVERFLOW(/* To: */ new_size, /* From: */ fspace->alloc_sect_size, /* From: */ hsize_t, /* To: */ size_t); - while(new_size < fspace->sect_size) - new_size *= (double)fspace->expand_percent / 100.0; - fspace->alloc_sect_size = new_size; - - /* Allocate space for the new serialized sections on disk */ -#ifdef QAK -HDfprintf(stderr, "%s: Allocating space for larger serialized sections, new_size = %Zu\n", FUNC, new_size); -HDfprintf(stderr, "%s: fspace->sect_size = %Hu\n", FUNC, fspace->sect_size); -#endif /* QAK */ - if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, (hsize_t)fspace->alloc_sect_size))) - HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") -#ifdef QAK -HDfprintf(stderr, "%s: old_addr = %a, fspace->sect_addr = %a\n", FUNC, old_addr, fspace->sect_addr); -#endif /* QAK */ - - /* Move object in cache, if it actually was relocated */ - if(H5F_addr_ne(fspace->sect_addr, old_addr)) { - if(H5AC_rename(f, H5AC_FSPACE_SINFO, old_addr, fspace->sect_addr) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTRENAME, FAIL, "unable to move free space section info") - } /* end if */ - else { - /* Mark free space section as dirty */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space section info as dirty") - } /* end else */ - - /* Mark free space header as dirty */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") - } /* end if */ - else { - size_t decrease_threshold; /* Size threshold for decreasing serialized section size */ - haddr_t old_addr; /* Old address of serialized sections */ - - /* Compute the threshold for decreasing the sections' serialized size */ - decrease_threshold = (size_t)(((size_t)fspace->alloc_sect_size * (double)fspace->shrink_percent) / 100.0); - - if(fspace->alloc_sect_size > H5FS_SINFO_SIZE_DEFAULT && - fspace->sect_size < decrease_threshold) { - size_t new_size = 0; /* New size of space for serialized sections */ - -/* Currently, the old block 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. - * - * This also keeps the file smaller, by freeing the space and then - * allocating new space, instead of vice versa (in H5MF_realloc). - * - * QAK - 5/ 8/2006 - */ - /* Free previous serialized sections disk space */ - old_addr = fspace->sect_addr; - if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_addr, fspace->alloc_sect_size) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections") - - /* Compute new size */ - while(fspace->sect_size < decrease_threshold) { - new_size = decrease_threshold; - - decrease_threshold *= (double)fspace->shrink_percent / 100.0; - } /* end while */ - if(new_size < H5FS_SINFO_SIZE_DEFAULT) - new_size = H5FS_SINFO_SIZE_DEFAULT; - fspace->alloc_sect_size = new_size; - - /* Allocate space for the new serialized sections on disk */ -#ifdef QAK -HDfprintf(stderr, "%s: Allocating space for smaller serialized sections, new_size = %Zu\n", FUNC, new_size); -#endif /* QAK */ - if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, (hsize_t)fspace->alloc_sect_size))) - HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") - - /* Move object in cache, if it actually was relocated */ - if(H5F_addr_ne(fspace->sect_addr, old_addr)) { - if(H5AC_rename(f, H5AC_FSPACE_SINFO, old_addr, fspace->sect_addr) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTRENAME, FAIL, "unable to move free space section info") - } /* end if */ - else { - /* Mark free space section as dirty */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space section info as dirty") - } /* end else */ - - /* Mark free space header as dirty */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") - } /* end if */ - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5FS_sect_serialize_size() */ - - -/*------------------------------------------------------------------------- * Function: H5FS_iterate_sect_cb * * Purpose: Skip list iterator callback to iterate over free space sections @@ -1533,7 +1885,8 @@ done: herr_t H5FS_sect_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, void *op_data) { - H5FS_iter_ud_t udata; /* User data for callbacks */ + H5FS_iter_ud_t udata; /* User data for callbacks */ + hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_iterate) @@ -1542,14 +1895,8 @@ H5FS_sect_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, v HDassert(fspace); HDassert(op); - /* 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 */ - #ifdef QAK -HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count); +HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count); #endif /* QAK */ /* Set up user data for iterator */ @@ -1561,6 +1908,11 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect if(fspace->tot_sect_count) { unsigned bin; /* Current bin we are on */ + /* Get a pointer to the section info */ + if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_READ) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info") + sinfo_valid = TRUE; + /* Iterate over all the bins */ #ifdef QAK HDfprintf(stderr, "%s: Iterate over section bins\n", FUNC); @@ -1576,17 +1928,20 @@ HDfprintf(stderr, "%s: Iterate over section bins\n", FUNC); } /* end if */ done: + /* Release the section info */ + if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, FALSE) < 0) + HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info") + FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_iterate() */ /*------------------------------------------------------------------------- - * Function: H5FS_get_sect_count + * Function: H5FS_sect_stats * - * Purpose: Retrieve the number of sections managed + * Purpose: Retrieve info about the sections managed * * Return: Success: non-negative - * * Failure: negative * * Programmer: Quincey Koziol @@ -1595,19 +1950,21 @@ done: *------------------------------------------------------------------------- */ herr_t -H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects) +H5FS_sect_stats(const H5FS_t *fspace, hsize_t *tot_space, hsize_t *nsects) { - FUNC_ENTER_NOAPI_NOFUNC(H5FS_get_sect_count) + FUNC_ENTER_NOAPI_NOFUNC(H5FS_sect_stats) /* Check arguments. */ HDassert(fspace); - HDassert(nsects); - /* Get the section count */ - *nsects = fspace->tot_sect_count; + /* Get the stats desired */ + if(tot_space) + *tot_space = fspace->tot_space; + if(nsects) + *nsects = fspace->tot_sect_count; FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5FS_get_sect_count() */ +} /* H5FS_sect_stats() */ /*------------------------------------------------------------------------- @@ -1632,17 +1989,22 @@ H5FS_sect_change_class(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_class_t *old_cls; /* Old class of section */ const H5FS_section_class_t *new_cls; /* New class of section */ unsigned old_class; /* Old class ID of section */ + hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_change_class) /* Check arguments. */ HDassert(fspace); - HDassert(fspace->sinfo); HDassert(sect); HDassert(sect->type < fspace->nclasses); HDassert(new_class < fspace->nclasses); + /* Get a pointer to the section info */ + if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info") + sinfo_valid = TRUE; + /* Get class info */ old_class = sect->type; old_cls = &fspace->sect_cls[sect->type]; @@ -1764,18 +2126,18 @@ HDfprintf(stderr, "%s: removing object from merge list, sect->type = %u\n", FUNC fspace->sinfo->serial_size += fspace->sect_cls[new_class].serial_size; /* Update current space used for free space sections */ - if(H5FS_sect_serialize_size(f, dxpl_id, fspace) < 0) + if(H5FS_sect_serialize_size(fspace) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTCOMPUTE, FAIL, "can't adjust free space section size on disk") - /* Mark free space sections as dirty */ - if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space sections as dirty") - done: + /* Release the section info */ + if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, TRUE) < 0) + HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info") + FUNC_LEAVE_NOAPI(ret_value) } /* H5FS_sect_change_class() */ -#ifdef H5FS_DEBUG +#ifdef H5FS_DEBUG_ASSERT /*------------------------------------------------------------------------- * Function: H5FS_sect_assert @@ -1796,8 +2158,8 @@ H5FS_sect_assert(const H5FS_t *fspace) hsize_t separate_obj; /* The number of separate objects managed */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_assert) -#ifdef QAK -HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", "H5FS_sect_assert", fspace->hdr->tot_sect_count); +#ifndef QAK +HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", "H5FS_sect_assert", fspace->tot_sect_count); #endif /* QAK */ /* Initialize state */ @@ -1925,5 +2287,5 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", "H FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5FS_sect_assert() */ -#endif /* H5FS_DEBUG */ +#endif /* H5FS_DEBUG_ASSERT */ diff --git a/src/H5FSstat.c b/src/H5FSstat.c new file mode 100644 index 0000000..7b2cb0d --- /dev/null +++ b/src/H5FSstat.c @@ -0,0 +1,101 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Purpose: Free-space metadata statistics functions. + * + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5FS_PACKAGE /*suppress error about including H5FSpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FSpkg.h" /* Free-space manager */ + +/****************/ +/* Local Macros */ +/****************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5FS_stat_info + * + * Purpose: Retrieve metadata statistics for the free-space manager + * + * Return: Success: non-negative + * + * Failure: does not fail + * + * Programmer: Vailin Choi + * August 25th, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_stat_info(const H5FS_t *frsp, H5FS_stat_t *stats) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_stat_info) + + /* Check arguments. */ + HDassert(frsp); + HDassert(stats); + + /* Report statistics for free space */ + stats->tot_space = frsp->tot_space; + stats->tot_sect_count = frsp->tot_sect_count; + stats->serial_sect_count = frsp->serial_sect_count; + stats->ghost_sect_count = frsp->ghost_sect_count; + /* can add more metadata statistics for the free-space manager */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5FS_stat_info() */ diff --git a/src/H5FStest.c b/src/H5FStest.c new file mode 100644 index 0000000..719e553 --- /dev/null +++ b/src/H5FStest.c @@ -0,0 +1,154 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Purpose: Free-space manager testing functions. + * + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5FS_PACKAGE /*suppress error about including H5FSpkg */ +#define H5FS_TESTING /*suppress warning about H5FS testing funcs */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FSpkg.h" /* Free-space manager */ + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5HF_get_cparam_test + * + * Purpose: Retrieve the parameters used to create the free-space manager + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: similar to H5HF_get_cparam_test() + * Vailin Choi; August 25th, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_get_cparam_test(const H5FS_t *frsp, H5FS_create_t *cparam) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_get_cparam_test) + + /* Check arguments. */ + HDassert(frsp); + HDassert(cparam); + + cparam->client = frsp->client; + cparam->shrink_percent = frsp->shrink_percent; + cparam->expand_percent = frsp->expand_percent; + cparam->max_sect_addr = frsp->max_sect_addr; + cparam->max_sect_size = frsp->max_sect_size; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5FS_get_cparam_test() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_cmp_cparam_test + * + * Purpose: Compare the parameters used to create the fractal heap + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: similar to H5HF_cmp_cparam_test() + * Vailin Choi; August 25th, 2008 + * + *------------------------------------------------------------------------- + */ +int +H5FS_cmp_cparam_test(const H5FS_create_t *cparam1, const H5FS_create_t *cparam2) +{ + int ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_cmp_cparam_test) + + /* Check arguments. */ + HDassert(cparam1); + HDassert(cparam2); + + if(cparam1->client < cparam2->client) + HGOTO_DONE(-1) + else if(cparam1->client > cparam2->client) + HGOTO_DONE(1) + + if(cparam1->shrink_percent < cparam2->shrink_percent) + HGOTO_DONE(-1) + else if(cparam1->shrink_percent > cparam2->shrink_percent) + HGOTO_DONE(1) + + if(cparam1->expand_percent < cparam2->expand_percent) + HGOTO_DONE(-1) + else if(cparam1->expand_percent > cparam2->expand_percent) + HGOTO_DONE(1) + + if(cparam1->max_sect_size < cparam2->max_sect_size) + HGOTO_DONE(-1) + else if(cparam1->max_sect_size > cparam2->max_sect_size) + HGOTO_DONE(1) + + if(cparam1->max_sect_addr < cparam2->max_sect_addr) + HGOTO_DONE(-1) + else if(cparam1->max_sect_addr > cparam2->max_sect_addr) + HGOTO_DONE(1) + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_cmp_cparam_test */ diff --git a/src/H5Faccum.c b/src/H5Faccum.c new file mode 100644 index 0000000..b9fe3e1 --- /dev/null +++ b/src/H5Faccum.c @@ -0,0 +1,655 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5Faccum.c + * Jan 10 2008 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: File metadata "accumulator" routines. (Used to + * cache small metadata I/Os and group them into a + * single larger I/O) + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5FDprivate.h" /* File drivers */ + + +/****************/ +/* Local Macros */ +/****************/ + +/* Metadata accumulator controls */ +#define H5F_ACCUM_THROTTLE 8 +#define H5F_ACCUM_THRESHOLD 2048 + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a PQ free list to manage the metadata accumulator buffer */ +H5FL_BLK_DEFINE_STATIC(meta_accum); + + + +/*------------------------------------------------------------------------- + * Function: H5F_accum_read + * + * Purpose: Attempts to read some data from the metadata accumulator for + * a file into a buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jan 10 2008 + * + *------------------------------------------------------------------------- + */ +htri_t +H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, + size_t size, void *buf/*out*/) +{ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_accum_read, FAIL) + + HDassert(f); + HDassert(f->shared); + HDassert(buf); + + /* Check if this information is in the metadata accumulator */ + if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) { + /* Current read overlaps with metadata accumulator */ + if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) { + unsigned char *read_buf = (unsigned char *)buf; /* Pointer to the buffer being read in */ + size_t amount_read; /* Amount to read at a time */ + hsize_t read_off; /* Offset to read from */ + + /* Read the part before the metadata accumulator */ + if(addr < f->shared->accum.loc) { + /* Set the amount to read */ + H5_ASSIGN_OVERFLOW(amount_read, (f->shared->accum.loc - addr), hsize_t, size_t); + + /* Dispatch to driver */ + if(H5FD_read(f->shared->lf, dxpl_id, type, addr, amount_read, read_buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed") + + /* Adjust the buffer, address & size */ + read_buf += amount_read; + addr += amount_read; + size -= amount_read; + } /* end if */ + + /* Copy the part overlapping the metadata accumulator */ + if(size > 0 && (addr >= f->shared->accum.loc && addr < (f->shared->accum.loc + f->shared->accum.size))) { + /* Set the offset to "read" from */ + read_off = addr - f->shared->accum.loc; + + /* Set the amount to "read" */ +#ifndef NDEBUG +{ + hsize_t tempamount_read; /* Amount to read at a time */ + + tempamount_read = f->shared->accum.size - read_off; + H5_CHECK_OVERFLOW(tempamount_read, hsize_t, size_t); + amount_read = MIN(size, (size_t)tempamount_read); +} +#else /* NDEBUG */ + amount_read = MIN(size, (size_t)(f->shared->accum.size - read_off)); +#endif /* NDEBUG */ + + /* Copy the data out of the buffer */ + HDmemcpy(read_buf, f->shared->accum.buf + read_off, amount_read); + + /* Adjust the buffer, address & size */ + read_buf += amount_read; + addr += amount_read; + size -= amount_read; + } /* end if */ + + /* Read the part after the metadata accumulator */ + if(size > 0 && addr >= (f->shared->accum.loc + f->shared->accum.size)) { + /* Dispatch to driver */ + if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, read_buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed") + + /* Adjust the buffer, address & size */ + read_buf += size; + addr += size; + size -= size; + } /* end if */ + + /* Make certain we've read it all */ + HDassert(size == 0); + } /* end if */ + /* Current read doesn't overlap with metadata accumulator, read it into accumulator */ + else { + /* Only update the metadata accumulator if it is not dirty or if + * we are allowed to write the accumulator out during reads (when + * it is dirty) + */ + if(f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA_READ || !f->shared->accum.dirty) { + /* Flush current contents, if dirty */ + if(f->shared->accum.dirty) { + if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "driver write request failed") + + /* Reset accumulator dirty flag */ + f->shared->accum.dirty = FALSE; + } /* end if */ + + /* Cache the new piece of metadata */ + /* Check if we need to resize the buffer */ + if(size > f->shared->accum.alloc_size) { + /* Grow the metadata accumulator buffer */ + if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") + + /* Note the new buffer size */ + f->shared->accum.alloc_size = size; + } /* end if */ + else { + /* Check if we should shrink the accumulator buffer */ + if(size < (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE) && + f->shared->accum.alloc_size > H5F_ACCUM_THRESHOLD) { + size_t new_size = (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE); /* New size of accumulator buffer */ + + /* Shrink the accumulator buffer */ + if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") + + /* Note the new buffer size */ + f->shared->accum.alloc_size = new_size; + } /* end if */ + } /* end else */ + + /* Update accumulator information */ + f->shared->accum.loc = addr; + f->shared->accum.size = size; + f->shared->accum.dirty = FALSE; + + /* Read into accumulator */ + if(H5FD_read(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed") + + /* Copy into buffer */ + HDmemcpy(buf, f->shared->accum.buf, size); + } /* end if */ + else { + /* Dispatch to driver */ + if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed") + } /* end else */ + } /* end else */ + + /* Indicate success */ + HGOTO_DONE(TRUE); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_accum_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_accum_write + * + * Purpose: Attempts to read some data from the metadata accumulator for + * a file into a buffer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jan 10 2008 + * + *------------------------------------------------------------------------- + */ +htri_t +H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, + size_t size, const void *buf) +{ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_accum_write, FAIL) + + HDassert(f); + HDassert(f->shared); + HDassert(f->intent & H5F_ACC_RDWR); + HDassert(buf); + + /* Check for accumulating metadata */ + if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) { + /* Check if there is already metadata in the accumulator */ + if(f->shared->accum.size > 0) { + /* Check if the piece of metadata being written adjoins or is inside the metadata accumulator */ + if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) { + size_t new_size; /* New size of the accumulator buffer */ + size_t old_offset; /* Offset of old data within the accumulator buffer */ + + /* Check if the new metadata adjoins the beginning of the current accumulator */ + if((addr + size) == f->shared->accum.loc) { + /* Check if we need more buffer space */ + if((size + f->shared->accum.size) > f->shared->accum.alloc_size) { + /* Adjust the buffer size, by doubling it */ + f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, size + f->shared->accum.size); + + /* Reallocate the metadata accumulator buffer */ + if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") +#ifdef H5_CLEAR_MEMORY +HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - (f->shared->accum.size + size))); +#endif /* H5_CLEAR_MEMORY */ + } /* end if */ + + /* Move the existing metadata to the proper location */ + HDmemmove(f->shared->accum.buf + size, f->shared->accum.buf, f->shared->accum.size); + + /* Copy the new metadata at the front */ + HDmemcpy(f->shared->accum.buf, buf, size); + + /* Set the new size & location of the metadata accumulator */ + f->shared->accum.loc = addr; + f->shared->accum.size += size; + + /* Mark it as written to */ + f->shared->accum.dirty = TRUE; + } /* end if */ + /* Check if the new metadata adjoins the end of the current accumulator */ + else if(addr == (f->shared->accum.loc + f->shared->accum.size)) { + /* Check if we need more buffer space */ + if((size + f->shared->accum.size) > f->shared->accum.alloc_size) { + /* Adjust the buffer size, by doubling it */ + f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, size + f->shared->accum.size); + + /* Reallocate the metadata accumulator buffer */ + if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") +#ifdef H5_CLEAR_MEMORY +HDmemset(f->shared->accum.buf + f->shared->accum.size + size, 0, (f->shared->accum.alloc_size - (f->shared->accum.size + size))); +#endif /* H5_CLEAR_MEMORY */ + } /* end if */ + + /* Copy the new metadata to the end */ + HDmemcpy(f->shared->accum.buf + f->shared->accum.size, buf, size); + + /* Set the new size of the metadata accumulator */ + f->shared->accum.size += size; + + /* Mark it as written to */ + f->shared->accum.dirty = TRUE; + } /* end if */ + /* Check if the new metadata is entirely within the current accumulator */ + else if(addr >= f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) { + /* Copy the new metadata to the proper location within the accumulator */ + HDmemcpy(f->shared->accum.buf + (addr - f->shared->accum.loc), buf, size); + + /* Mark it as written to */ + f->shared->accum.dirty = TRUE; + } /* end if */ + /* Check if the new metadata overlaps the beginning of the current accumulator */ + else if(addr < f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) { + /* Calculate the new accumulator size, based on the amount of overlap */ + H5_ASSIGN_OVERFLOW(new_size, (f->shared->accum.loc - addr) + f->shared->accum.size, hsize_t, size_t); + + /* Check if we need more buffer space */ + if(new_size > f->shared->accum.alloc_size) { + /* Adjust the buffer size, by doubling it */ + f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size + 2, new_size); + + /* Reallocate the metadata accumulator buffer */ + if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") +#ifdef H5_CLEAR_MEMORY +HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size)); +#endif /* H5_CLEAR_MEMORY */ + } /* end if */ + + /* Calculate the proper offset of the existing metadata */ + H5_ASSIGN_OVERFLOW(old_offset, (addr + size) - f->shared->accum.loc, hsize_t, size_t); + + /* Move the existing metadata to the proper location */ + HDmemmove(f->shared->accum.buf + size, f->shared->accum.buf + old_offset, (f->shared->accum.size - old_offset)); + + /* Copy the new metadata at the front */ + HDmemcpy(f->shared->accum.buf, buf, size); + + /* Set the new size & location of the metadata accumulator */ + f->shared->accum.loc = addr; + f->shared->accum.size = new_size; + + /* Mark it as written to */ + f->shared->accum.dirty = TRUE; + } /* end if */ + /* Check if the new metadata overlaps the end of the current accumulator */ + else if(addr >= f->shared->accum.loc && (addr + size) > (f->shared->accum.loc + f->shared->accum.size)) { + /* Calculate the new accumulator size, based on the amount of overlap */ + H5_ASSIGN_OVERFLOW(new_size, (addr - f->shared->accum.loc) + size, hsize_t, size_t); + + /* Check if we need more buffer space */ + if(new_size > f->shared->accum.alloc_size) { + /* Adjust the buffer size, by doubling it */ + f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, new_size); + + /* Reallocate the metadata accumulator buffer */ + if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") +#ifdef H5_CLEAR_MEMORY +HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size)); +#endif /* H5_CLEAR_MEMORY */ + } /* end if */ + + /* Copy the new metadata to the end */ + HDmemcpy(f->shared->accum.buf + (addr - f->shared->accum.loc), buf, size); + + /* Set the new size & location of the metadata accumulator */ + f->shared->accum.size = new_size; + + /* Mark it as written to */ + f->shared->accum.dirty = TRUE; + } /* end if */ + else { + HDassert(0 && "New metadata overlapped both beginning and end of existing metadata accumulator!"); + } /* end else */ + } /* end if */ + /* New piece of metadata doesn't adjoin or overlap the existing accumulator */ + else { + /* Write out the existing metadata accumulator, with dispatch to driver */ + if(f->shared->accum.dirty) { + if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed") + + /* Reset accumulator dirty flag */ + f->shared->accum.dirty = FALSE; + } /* end if */ + + /* Cache the new piece of metadata */ + /* Check if we need to resize the buffer */ + if(size > f->shared->accum.alloc_size) { + /* Grow the metadata accumulator buffer */ + if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") + + /* Note the new buffer size */ + f->shared->accum.alloc_size = size; +#ifdef H5_CLEAR_MEMORY +{ +size_t clear_size = MAX(f->shared->accum.size, size); +HDmemset(f->shared->accum.buf + clear_size, 0, (f->shared->accum.alloc_size - clear_size)); +} +#endif /* H5_CLEAR_MEMORY */ + } /* end if */ + else { + /* Check if we should shrink the accumulator buffer */ + if(size < (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE) && + f->shared->accum.alloc_size > H5F_ACCUM_THRESHOLD) { + size_t tmp_size = (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE); /* New size of accumulator buffer */ + + /* Shrink the accumulator buffer */ + if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, tmp_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") + + /* Note the new buffer size */ + f->shared->accum.alloc_size = tmp_size; + } /* end if */ + } /* end else */ + + /* Update the metadata accumulator information */ + f->shared->accum.loc = addr; + f->shared->accum.size = size; + f->shared->accum.dirty = TRUE; + + /* Store the piece of metadata in the accumulator */ + HDmemcpy(f->shared->accum.buf, buf, size); + } /* end else */ + } /* end if */ + /* No metadata in the accumulator, grab this piece and keep it */ + else { + /* Check if we need to reallocate the buffer */ + if(size > f->shared->accum.alloc_size) { + /* Reallocate the metadata accumulator buffer */ + if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer") + + /* Note the new buffer size */ + f->shared->accum.alloc_size = size; + } /* end if */ + + /* Update the metadata accumulator information */ + f->shared->accum.loc = addr; + f->shared->accum.size = size; + f->shared->accum.dirty = TRUE; + + /* Store the piece of metadata in the accumulator */ + HDmemcpy(f->shared->accum.buf, buf, size); + } /* end else */ + + /* Indicate success */ + HGOTO_DONE(TRUE); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_accum_write() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_accum_free + * + * Purpose: Check for free space invalidating [part of] a metadata + * accumulator. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jan 10 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, + hsize_t size) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_accum_free, FAIL) + + /* check arguments */ + HDassert(f); + + /* Adjust the metadata accumulator to remove the freed block, if it overlaps */ + if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) + && H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) { + size_t overlap_size; /* Size of overlap with accumulator */ + + /* Sanity check */ + /* (The metadata accumulator should not intersect w/raw data */ + HDassert(H5FD_MEM_DRAW != type); + + /* Check for overlapping the beginning of the accumulator */ + if(H5F_addr_le(addr, f->shared->accum.loc)) { + /* Check for completely overlapping the accumulator */ + if(H5F_addr_ge(addr + size, f->shared->accum.loc + f->shared->accum.size)) { + /* Reset the accumulator, but don't free buffer */ + f->shared->accum.loc = HADDR_UNDEF; + f->shared->accum.size = 0; + f->shared->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) - f->shared->accum.loc, haddr_t, size_t); + new_accum_size = f->shared->accum.size - overlap_size; + + /* Move the accumulator buffer information to eliminate the freed block */ + HDmemmove(f->shared->accum.buf, f->shared->accum.buf + overlap_size, new_accum_size); + + /* Adjust the accumulator information */ + f->shared->accum.loc += overlap_size; + f->shared->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, (f->shared->accum.loc + f->shared->accum.size) - addr, haddr_t, size_t); + + /* Block to free is in the middle of the accumulator */ + if(H5F_addr_lt((addr + size), f->shared->accum.loc + f->shared->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, (f->shared->accum.loc + f->shared->accum.size) - tail_addr, haddr_t, size_t); + + /* Write out the part of the accumulator after the block to free */ + if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, tail_addr, tail_size, f->shared->accum.buf + (tail_addr - f->shared->accum.loc)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed") + } /* end if */ + + /* Adjust the accumulator information */ + f->shared->accum.size = f->shared->accum.size - overlap_size; + } /* end else */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_accum_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_accum_flush + * + * Purpose: Flush the metadata accumulator to the file + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jan 10 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_accum_flush(H5F_t *f, hid_t dxpl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_accum_flush, FAIL) + + HDassert(f); + HDassert(f->shared); + + /* Check if we need to flush out the metadata accumulator */ + if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && f->shared->accum.dirty && f->shared->accum.size > 0) { + /* Flush the metadata contents */ + if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed") + + /* Reset the dirty flag */ + f->shared->accum.dirty = FALSE; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_accum_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_accum_reset + * + * Purpose: Reset the metadata accumulator for the file + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jan 10 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_accum_reset(H5F_t *f) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5F_accum_reset) + + HDassert(f); + HDassert(f->shared); + + /* Check if we need to reset the metadata accumulator information */ + if(f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) { + /* Sanity check */ + HDassert(!f->closing || FALSE == f->shared->accum.dirty); + + /* Free the buffer */ + if(f->shared->accum.buf) + f->shared->accum.buf = H5FL_BLK_FREE(meta_accum, f->shared->accum.buf); + + /* Reset the buffer sizes & location */ + f->shared->accum.alloc_size = f->shared->accum.size = 0; + f->shared->accum.loc = HADDR_UNDEF; + f->shared->accum.dirty = FALSE; + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5F_accum_reset() */ + + diff --git a/src/H5Fdbg.c b/src/H5Fdbg.c index 9d4e6e9..e05c32a 100644 --- a/src/H5Fdbg.c +++ b/src/H5Fdbg.c @@ -82,7 +82,7 @@ H5F_debug(H5F_t *f, FILE *stream, int indent, int fwidth) HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "File open reference count:", f->shared->nrefs); HDfprintf(stream, "%*s%-*s %a (abs)\n", indent, "", fwidth, - "Address of super block:", f->shared->super_addr); + "Address of super block:", f->shared->base_addr); HDfprintf(stream, "%*s%-*s %Hu bytes\n", indent, "", fwidth, "Size of userblock:", userblock_size); @@ -107,8 +107,6 @@ H5F_debug(H5F_t *f, FILE *stream, int indent, int fwidth) "Symbol table internal node 1/2 rank:", f->shared->btree_k[H5B_SNODE_ID]); HDfprintf(stream, "%*s%-*s 0x%02x\n", indent, "", fwidth, "File status flags:", (unsigned)(f->shared->status_flags)); - HDfprintf(stream, "%*s%-*s %a (abs)\n", indent, "", fwidth, - "Base address:", f->shared->base_addr); HDfprintf(stream, "%*s%-*s %a (rel)\n", indent, "", fwidth, "Superblock extension address:", f->shared->extension_addr); HDfprintf(stream, "%*s%-*s %a (rel)\n", indent, "", fwidth, diff --git a/src/H5Fio.c b/src/H5Fio.c new file mode 100644 index 0000000..1081a27 --- /dev/null +++ b/src/H5Fio.c @@ -0,0 +1,165 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5Fio.c + * Jan 10 2008 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: File I/O routines. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5FDprivate.h" /* File drivers */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5F_block_read + * + * Purpose: Reads some data from a file/server/etc into a buffer. + * The data is contiguous. The address is relative to the base + * address for the file. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 10 1997 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, + hid_t dxpl_id, void *buf/*out*/) +{ + htri_t accumulated; /* Whether the data was accepted by the metadata accumulator */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_block_read, FAIL) + + HDassert(f); + HDassert(f->shared); + HDassert(buf); + + /* Check if this I/O can be satisfied by the metadata accumulator */ + if((accumulated = H5F_accum_read(f, dxpl_id, type, addr, size, buf)) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read from metadata accumulator failed") + else if(accumulated == FALSE) { + /* Read the data */ + if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_block_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_block_write + * + * Purpose: Writes some data from memory to a file/server/etc. The + * data is contiguous. The address is relative to the base + * address. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 10 1997 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_block_write(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, + hid_t dxpl_id, const void *buf) +{ + htri_t accumulated; /* Whether the data was accepted by the metadata accumulator */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_block_write, FAIL) +#ifdef QAK +HDfprintf(stderr, "%s: write to addr = %a, size = %Zu\n", FUNC, addr, size); +#endif /* QAK */ + + HDassert(f); + HDassert(f->shared); + HDassert(f->intent & H5F_ACC_RDWR); + HDassert(buf); + + /* Check for accumulating metadata */ + if((accumulated = H5F_accum_write(f, dxpl_id, type, addr, size, buf)) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write to metadata accumulator failed") + else if(accumulated == FALSE) { + /* Write the data */ + if(H5FD_write(f->shared->lf, dxpl_id, type, addr, size, buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_block_write() */ + diff --git a/src/H5Fmpi.c b/src/H5Fmpi.c new file mode 100644 index 0000000..c90ad7c --- /dev/null +++ b/src/H5Fmpi.c @@ -0,0 +1,181 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5Fmpi.c + * Jan 10 2008 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: MPI-related routines. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5FDmpi.h" /* MPI-based file drivers */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + +#ifdef H5_HAVE_PARALLEL + +/*------------------------------------------------------------------------- + * Function: H5F_mpi_get_rank + * + * Purpose: Retrieves the rank of an MPI process. + * + * Return: Success: The rank (non-negative) + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * Friday, January 30, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5F_mpi_get_rank(const H5F_t *f) +{ + int ret_value; + + FUNC_ENTER_NOAPI(H5F_mpi_get_rank, FAIL) + + assert(f && f->shared); + + /* Dispatch to driver */ + if ((ret_value=H5FD_mpi_get_rank(f->shared->lf)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_rank request failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_mpi_get_rank() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_mpi_get_comm + * + * Purpose: Retrieves the file's communicator + * + * Return: Success: The communicator (non-negative) + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * Friday, January 30, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +MPI_Comm +H5F_mpi_get_comm(const H5F_t *f) +{ + MPI_Comm ret_value; + + FUNC_ENTER_NOAPI(H5F_mpi_get_comm, MPI_COMM_NULL) + + assert(f && f->shared); + + /* Dispatch to driver */ + if ((ret_value=H5FD_mpi_get_comm(f->shared->lf))==MPI_COMM_NULL) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_COMM_NULL, "driver get_comm request failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_mpi_get_comm() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_mpi_get_size + * + * Purpose: Retrieves the size of an MPI process. + * + * Return: Success: The size (positive) + * + * Failure: Negative + * + * Programmer: John Mainzer + * Friday, May 6, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5F_mpi_get_size(const H5F_t *f) +{ + int ret_value; + + FUNC_ENTER_NOAPI(H5F_mpi_get_size, FAIL) + + assert(f && f->shared); + + /* Dispatch to driver */ + if ((ret_value=H5FD_mpi_get_size(f->shared->lf)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_size request failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_mpi_get_size() */ +#endif /* H5_HAVE_PARALLEL */ + diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 594ed50..428b58d 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -38,6 +38,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5FLprivate.h" /* Free Lists */ #include "H5FOprivate.h" /* File objects */ +#include "H5FSprivate.h" /* File free space */ #include "H5Gprivate.h" /* Groups */ #include "H5Oprivate.h" /* Object header messages */ #include "H5RCprivate.h" /* Reference counted object functions */ @@ -62,6 +63,35 @@ /* Mask for removing private file access flags */ #define H5F_ACC_PUBLIC_FLAGS 0x00ffu +/* Free space section+aggregator merge flags */ +#define H5F_FS_MERGE_METADATA 0x01 /* Section can merge with metadata aggregator */ +#define H5F_FS_MERGE_RAWDATA 0x02 /* Section can merge with small 'raw' data aggregator */ + +/* Structure for metadata & "small [raw] data" block aggregation fields */ +struct H5F_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 */ +}; + +/* Structure for metadata accumulator fields */ +typedef struct H5F_meta_accum_t { + unsigned char *buf; /* Buffer to hold the accumulated metadata */ + haddr_t loc; /* File location (offset) of the accumulated metadata */ + size_t size; /* Size of the accumulated metadata buffer used (in bytes) */ + size_t alloc_size; /* Size of the accumulated metadata buffer allocated (in bytes) */ + hbool_t dirty; /* Flag to indicate that the accumulated metadata is dirty */ +} H5F_meta_accum_t; + +/* Enum for free space manager state */ +typedef enum H5F_fs_state_t { + H5F_FS_STATE_CLOSED, /* Free space manager is closed */ + H5F_FS_STATE_OPEN, /* Free space manager has been opened */ + H5F_FS_STATE_DELETING /* Free space manager is being deleted */ +} H5F_fs_state_t; + /* A record of the mount table */ typedef struct H5F_mount_t { struct H5G_t *group; /* Mount point group held open */ @@ -97,13 +127,14 @@ typedef struct H5F_file_t { unsigned btree_k[H5B_NUM_BTREE_ID]; /* B-tree key values for each type */ size_t sizeof_addr; /* Size of addresses in file */ size_t sizeof_size; /* Size of offsets in file */ - haddr_t super_addr; /* Absolute address of super block */ haddr_t base_addr; /* Absolute base address for rel.addrs. */ + /* (superblock for file is at this offset) */ haddr_t extension_addr; /* Relative address of superblock extension */ haddr_t sohm_addr; /* Relative address of shared object header message table */ 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*/ + unsigned long feature_flags; /* VFL Driver feature Flags */ haddr_t maxaddr; /* Maximum address for file */ H5AC_t *cache; /* The object cache */ @@ -129,6 +160,20 @@ typedef struct H5F_file_t { struct H5G_t *root_grp; /* Open root group */ H5FO_t *open_objs; /* Open objects in file */ H5RC_t *grp_btree_shared; /* Ref-counted group B-tree node info */ + + /* File space allocation information */ + unsigned fs_aggr_merge[H5FD_MEM_NTYPES]; /* Flags for whether free space can merge with aggregator(s) */ + H5F_fs_state_t fs_state[H5FD_MEM_NTYPES]; /* State of free space manager for each type */ + haddr_t fs_addr[H5FD_MEM_NTYPES]; /* Address of free space manager info for each type */ + H5FS_t *fs_man[H5FD_MEM_NTYPES]; /* Free space manager for each file space type */ + H5FD_mem_t fs_type_map[H5FD_MEM_NTYPES]; /* Mapping of "real" file space type into tracked type */ + H5F_blk_aggr_t meta_aggr; /* Metadata aggregation info */ + /* (if aggregating metadata allocations) */ + H5F_blk_aggr_t sdata_aggr; /* "Small data" aggregation info */ + /* (if aggregating "small data" allocations) */ + + /* Metadata accumulator information */ + H5F_meta_accum_t accum; /* Metadata accumulator info */ } H5F_file_t; /* @@ -182,6 +227,15 @@ H5_DLL herr_t H5F_super_write(H5F_t *f, hid_t dxpl_id); H5_DLL herr_t H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc); H5_DLL herr_t H5F_super_ext_size(H5F_t *f, hid_t dxpl_id, hsize_t *super_ext_info); +/* Metadata accumulator routines */ +H5_DLL htri_t H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, + haddr_t addr, size_t size, void *buf); +H5_DLL htri_t H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, + haddr_t addr, size_t size, const void *buf); +H5_DLL herr_t H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, + haddr_t addr, hsize_t size); +H5_DLL herr_t H5F_accum_flush(H5F_t *f, hid_t dxpl_id); +H5_DLL herr_t H5F_accum_reset(H5F_t *f); /* Shared file list related routines */ H5_DLL herr_t H5F_sfile_add(H5F_file_t *shared); diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 7583375..79e5218 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -35,6 +35,9 @@ /* Main file structure */ typedef struct H5F_t H5F_t; +/* Block aggregation structure */ +typedef struct H5F_blk_aggr_t H5F_blk_aggr_t; + /*===----------------------------------------------------------------------=== * Flush Flags *===----------------------------------------------------------------------=== @@ -214,7 +217,7 @@ typedef struct H5F_t H5F_t; HADDR_UNDEF==(X)+(haddr_t)(Z) || \ (X)+(haddr_t)(Z)<(X)) #define H5F_addr_hash(X,M) ((unsigned)((X)%(M))) -#define H5F_addr_defined(X) (X!=HADDR_UNDEF) +#define H5F_addr_defined(X) ((X)!=HADDR_UNDEF) /* The H5F_addr_eq() macro guarantees that Y is not HADDR_UNDEF by making * certain that X is not HADDR_UNDEF and then checking that X equals Y */ @@ -233,43 +236,36 @@ typedef struct H5F_t H5F_t; #define H5F_addr_ge(X,Y) ((X)!=HADDR_UNDEF && \ (Y)!=HADDR_UNDEF && \ (X)>=(Y)) -#define H5F_addr_cmp(X,Y) (H5F_addr_eq(X,Y)?0: \ - (H5F_addr_lt(X, Y)?-1:1)) +#define H5F_addr_cmp(X,Y) (H5F_addr_eq((X), (Y)) ? 0 : \ + (H5F_addr_lt((X), (Y)) ? -1 : 1)) #define H5F_addr_pow2(N) ((haddr_t)1<<(N)) -#define H5F_addr_overlap(O1,L1,O2,L2) ((O1<O2 && (O1+L1)>O2) || \ - (O1>=O2 && O1<(O2+L2))) +#define H5F_addr_overlap(O1,L1,O2,L2) (((O1) < (O2) && ((O1) + (L1)) > (O2)) || \ + ((O1) >= (O2) && (O1) < ((O2) + (L2)))) /* If the module using this macro is allowed access to the private variables, access them directly */ #ifdef H5F_PACKAGE -/* The FCPL itself */ +#define H5F_INTENT(F) ((F)->intent) #define H5F_FCPL(F) ((F)->shared->fcpl_id) -/* size of size_t and off_t as they exist on disk */ #define H5F_SIZEOF_ADDR(F) ((F)->shared->sizeof_addr) #define H5F_SIZEOF_SIZE(F) ((F)->shared->sizeof_size) -/* Size of symbol table leafs */ #define H5F_SYM_LEAF_K(F) ((F)->shared->sym_leaf_k) -/* B-tree key value size */ #define H5F_KVALUE(F,T) ((F)->shared->btree_k[(T)->id]) -/* Raw data cache values */ #define H5F_RDCC_NELMTS(F) ((F)->shared->rdcc_nelmts) #define H5F_RDCC_NBYTES(F) ((F)->shared->rdcc_nbytes) #define H5F_RDCC_W0(F) ((F)->shared->rdcc_w0) -/* Check for file driver feature enabled */ -#define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags & (FL)) -/* B-tree node raw page */ -#define H5F_GRP_BTREE_SHARED(F) ((F)->shared->grp_btree_shared) -/* Base address of file */ #define H5F_BASE_ADDR(F) ((F)->shared->base_addr) -/* Sieve buffer size for datasets */ +#define H5F_GRP_BTREE_SHARED(F) ((F)->shared->grp_btree_shared) #define H5F_SIEVE_BUF_SIZE(F) ((F)->shared->sieve_buf_size) #define H5F_GC_REF(F) ((F)->shared->gc_ref) #define H5F_USE_LATEST_FORMAT(F) ((F)->shared->latest_format) -#define H5F_INTENT(F) ((F)->intent) #define H5F_EXTPATH(F) ((F)->extpath) #define H5F_GET_FC_DEGREE(F) ((F)->shared->fc_degree) #define H5F_STORE_MSG_CRT_IDX(F) ((F)->shared->store_msg_crt_idx) +#define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags & (FL)) +#define H5F_DRIVER_ID(F) ((F)->shared->lf->driver_id) #define H5F_GET_FILENO(F,FILENUM) ((FILENUM) = (F)->shared->lf->fileno) #else /* H5F_PACKAGE */ +#define H5F_INTENT(F) (H5F_get_intent(F)) #define H5F_FCPL(F) (H5F_get_fcpl(F)) #define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F)) #define H5F_SIZEOF_SIZE(F) (H5F_sizeof_size(F)) @@ -278,17 +274,17 @@ typedef struct H5F_t H5F_t; #define H5F_RDCC_NELMTS(F) (H5F_rdcc_nelmts(F)) #define H5F_RDCC_NBYTES(F) (H5F_rdcc_nbytes(F)) #define H5F_RDCC_W0(F) (H5F_rdcc_w0(F)) -#define H5F_HAS_FEATURE(F,FL) (H5F_has_feature(F,FL)) -#define H5F_GRP_BTREE_SHARED(F) (H5F_grp_btree_shared(F)) #define H5F_BASE_ADDR(F) (H5F_get_base_addr(F)) +#define H5F_GRP_BTREE_SHARED(F) (H5F_grp_btree_shared(F)) #define H5F_SIEVE_BUF_SIZE(F) (H5F_sieve_buf_size(F)) #define H5F_GC_REF(F) (H5F_gc_ref(F)) #define H5F_USE_LATEST_FORMAT(F) (H5F_use_latest_format(F)) -#define H5F_INTENT(F) (H5F_get_intent(F)) #define H5F_EXTPATH(F) (H5F_get_extpath(F)) #define H5F_GET_FC_DEGREE(F) (H5F_get_fc_degree(F)) -#define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F)) -#define H5F_GET_FILENO(F,FILENUM) (H5F_get_filenum((F), &(FILENUM))) +#define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F)) +#define H5F_HAS_FEATURE(F,FL) (H5F_has_feature(F,FL)) +#define H5F_DRIVER_ID(F) (H5F_get_driver_id(F)) +#define H5F_GET_FILENO(F,FILENUM) (H5F_get_fileno((F), &(FILENUM))) #endif /* H5F_PACKAGE */ @@ -462,40 +458,27 @@ struct H5RC_t; H5_DLL H5F_t *H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id); H5_DLL herr_t H5F_try_close(H5F_t *f); +H5_DLL unsigned H5F_incr_nopen_objs(H5F_t *f); +H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f); /* Functions than retrieve values from the file struct */ -H5_DLL hid_t H5F_get_driver_id(const H5F_t *f); -H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref); H5_DLL unsigned H5F_get_intent(const H5F_t *f); +H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref); H5_DLL char *H5F_get_extpath(const H5F_t *f); -H5_DLL herr_t H5F_get_fileno(const H5F_t *f, unsigned long *filenum); H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref); H5_DLL size_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref); H5_DLL size_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref); -H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f); -H5_DLL haddr_t H5F_get_eoa(const H5F_t *f); -#ifdef H5_HAVE_PARALLEL -H5_DLL int H5F_mpi_get_rank(const H5F_t *f); -H5_DLL MPI_Comm H5F_mpi_get_comm(const H5F_t *f); -H5_DLL int H5F_mpi_get_size(const H5F_t *f); -#endif /* H5_HAVE_PARALLEL */ -H5_DLL unsigned H5F_incr_nopen_objs(H5F_t *f); -H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f); - -/* Functions than check file mounting information */ -H5_DLL hbool_t H5F_is_mount(const H5F_t *file); -H5_DLL hbool_t H5F_has_mount(const H5F_t *file); -/* Functions than retrieve values set from the FCPL */ +/* Functions than retrieve values set/cached from the superblock/FCPL */ H5_DLL hid_t H5F_get_fcpl(const H5F_t *f); H5_DLL size_t H5F_sizeof_addr(const H5F_t *f); H5_DLL size_t H5F_sizeof_size(const H5F_t *f); H5_DLL unsigned H5F_sym_leaf_k(const H5F_t *f); H5_DLL unsigned H5F_Kvalue(const H5F_t *f, const struct H5B_class_t *type); -H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature); H5_DLL size_t H5F_rdcc_nbytes(const H5F_t *f); H5_DLL size_t H5F_rdcc_nelmts(const H5F_t *f); H5_DLL double H5F_rdcc_w0(const H5F_t *f); +H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f); H5_DLL struct H5RC_t *H5F_grp_btree_shared(const H5F_t *f); H5_DLL size_t H5F_sieve_buf_size(const H5F_t *f); H5_DLL unsigned H5F_gc_ref(const H5F_t *f); @@ -503,6 +486,16 @@ H5_DLL hbool_t H5F_use_latest_format(const H5F_t *f); H5_DLL H5F_close_degree_t H5F_get_fc_degree(const H5F_t *f); H5_DLL hbool_t H5F_store_msg_crt_idx(const H5F_t *f); +/* Functions that retrieve values from VFD layer */ +H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature); +H5_DLL hid_t H5F_get_driver_id(const H5F_t *f); +H5_DLL herr_t H5F_get_fileno(const H5F_t *f, unsigned long *filenum); +H5_DLL haddr_t H5F_get_eoa(const H5F_t *f, H5FD_mem_t type); + +/* Functions than check file mounting information */ +H5_DLL hbool_t H5F_is_mount(const H5F_t *file); +H5_DLL hbool_t H5F_has_mount(const H5F_t *file); + /* Functions that operate on blocks of bytes wrt super block */ H5_DLL herr_t H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, hid_t dxpl_id, void *buf/*out*/); @@ -524,6 +517,13 @@ H5_DLL herr_t H5F_sfile_assert_num(unsigned n); H5_DLL H5F_t *H5F_fake_alloc(size_t sizeof_size); H5_DLL herr_t H5F_fake_free(H5F_t *f); +/* Parallel I/O (i.e. MPI) related routines */ +#ifdef H5_HAVE_PARALLEL +H5_DLL int H5F_mpi_get_rank(const H5F_t *f); +H5_DLL MPI_Comm H5F_mpi_get_comm(const H5F_t *f); +H5_DLL int H5F_mpi_get_size(const H5F_t *f); +#endif /* H5_HAVE_PARALLEL */ + /* Debugging functions */ H5_DLL herr_t H5F_debug(H5F_t *f, FILE * stream, int indent, int fwidth); diff --git a/src/H5Fquery.c b/src/H5Fquery.c new file mode 100644 index 0000000..3b93fb5 --- /dev/null +++ b/src/H5Fquery.c @@ -0,0 +1,663 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5Fquery.c + * Jan 10 2008 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: File structure query routines. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5FDprivate.h" /* File drivers */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5F_get_intent + * + * Purpose: Quick and dirty routine to retrieve the file's 'intent' flags + * (Mainly added to stop non-file routines from poking about in the + * H5F_t data structure) + * + * Return: 'intent' on success/abort on failure (shouldn't fail) + * + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * September 29, 2000 + * + *------------------------------------------------------------------------- + */ +unsigned +H5F_get_intent(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_intent) + + HDassert(f); + + FUNC_LEAVE_NOAPI(f->intent) +} /* end H5F_get_intent() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_extpath + * + * Purpose: Retrieve the file's 'extpath' flags + * This is used by H5L_extern_traverse() to retrieve the main file's location + * when searching the target file. + * + * Return: 'extpath' on success/abort on failure (shouldn't fail) + * + * Programmer: Vailin Choi, April 2, 2008 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +char * +H5F_get_extpath(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_extpath) + + HDassert(f); + + FUNC_LEAVE_NOAPI(f->extpath) +} /* end H5F_get_extpath() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_fcpl + * + * Purpose: Retrieve the value of a file's FCPL. + * + * Return: Success: The FCPL for the file. + * + * Failure: ? (should not happen) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 25 2005 + * + *------------------------------------------------------------------------- + */ +hid_t +H5F_get_fcpl(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fcpl) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->fcpl_id) +} /* end H5F_get_fcpl() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_sizeof_addr + * + * Purpose: Quick and dirty routine to retrieve the size of the file's size_t + * (Mainly added to stop non-file routines from poking about in the + * H5F_t data structure) + * + * Return: 'sizeof_addr' on success/abort on failure (shouldn't fail) + * + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * September 29, 2000 + * + *------------------------------------------------------------------------- + */ +size_t +H5F_sizeof_addr(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_addr) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->sizeof_addr) +} /* end H5F_sizeof_addr() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_sizeof_size + * + * Purpose: Quick and dirty routine to retrieve the size of the file's off_t + * (Mainly added to stop non-file routines from poking about in the + * H5F_t data structure) + * + * Return: 'sizeof_size' on success/abort on failure (shouldn't fail) + * + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * September 29, 2000 + * + *------------------------------------------------------------------------- + */ +size_t +H5F_sizeof_size(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_size) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->sizeof_size) +} /* H5F_sizeof_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_sym_leaf_k + * + * Purpose: Replaced a macro to retrieve the symbol table leaf size, + * now that the generic properties are being used to store + * the values. + * + * Return: Success: Non-negative, and the symbol table leaf size is + * returned. + * + * Failure: Negative (should not happen) + * + * Programmer: Raymond Lu + * slu@ncsa.uiuc.edu + * Oct 14 2001 + * + *------------------------------------------------------------------------- + */ +unsigned +H5F_sym_leaf_k(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sym_leaf_k) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->sym_leaf_k) +} /* end H5F_sym_leaf_k() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_Kvalue + * + * Purpose: Replaced a macro to retrieve a B-tree key value for a certain + * type, now that the generic properties are being used to store + * the B-tree values. + * + * Return: Success: Non-negative, and the B-tree key value is + * returned. + * + * Failure: Negative (should not happen) + * + * Programmer: Raymond Lu + * slu@ncsa.uiuc.edu + * Oct 14 2001 + * + *------------------------------------------------------------------------- + */ +unsigned +H5F_Kvalue(const H5F_t *f, const H5B_class_t *type) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_Kvalue) + + HDassert(f); + HDassert(f->shared); + HDassert(type); + + FUNC_LEAVE_NOAPI(f->shared->btree_k[type->id]) +} /* end H5F_Kvalue() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_rdcc_nelmts + * + * Purpose: Replaced a macro to retrieve the raw data cache number of elments, + * now that the generic properties are being used to store + * the values. + * + * Return: Success: Non-negative, and the raw data cache number of + * of elemnts is returned. + * + * Failure: Negative (should not happen) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jun 1 2004 + * + *------------------------------------------------------------------------- + */ +size_t +H5F_rdcc_nelmts(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nelmts) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->rdcc_nelmts) +} /* end H5F_rdcc_nelmts() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_rdcc_nbytes + * + * Purpose: Replaced a macro to retrieve the raw data cache number of bytes, + * now that the generic properties are being used to store + * the values. + * + * Return: Success: Non-negative, and the raw data cache number of + * of bytes is returned. + * + * Failure: Negative (should not happen) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jun 1 2004 + * + *------------------------------------------------------------------------- + */ +size_t +H5F_rdcc_nbytes(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nbytes) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->rdcc_nbytes) +} /* end H5F_rdcc_nbytes() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_rdcc_w0 + * + * Purpose: Replaced a macro to retrieve the raw data cache 'w0' value + * now that the generic properties are being used to store + * the values. + * + * Return: Success: Non-negative, and the raw data cache 'w0' value + * is returned. + * + * Failure: Negative (should not happen) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jun 2 2004 + * + *------------------------------------------------------------------------- + */ +double +H5F_rdcc_w0(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_w0) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->rdcc_w0) +} /* end H5F_rdcc_w0() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_base_addr + * + * Purpose: Quick and dirty routine to retrieve the file's 'base_addr' value + * (Mainly added to stop non-file routines from poking about in the + * H5F_t data structure) + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu <slu@ncsa.uiuc.edu> + * December 20, 2002 + * + *------------------------------------------------------------------------- + */ +haddr_t +H5F_get_base_addr(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_base_addr) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->base_addr) +} /* end H5F_get_base_addr() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_grp_btree_shared + * + * Purpose: Replaced a macro to retrieve the shared B-tree node info + * now that the generic properties are being used to store + * the values. + * + * Return: Success: Non-void, and the shared B-tree node info + * is returned. + * + * Failure: void (should not happen) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jul 5 2004 + * + *------------------------------------------------------------------------- + */ +H5RC_t * +H5F_grp_btree_shared(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_grp_btree_shared) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->grp_btree_shared) +} /* end H5F_grp_btree_shared() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_sieve_buf_size + * + * Purpose: Replaced a macro to retrieve the dataset sieve buffer size + * now that the generic properties are being used to store + * the values. + * + * Return: Success: Non-void, and the dataset sieve buffer size + * is returned. + * + * Failure: void (should not happen) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jul 8 2005 + * + *------------------------------------------------------------------------- + */ +size_t +H5F_sieve_buf_size(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sieve_buf_size) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->sieve_buf_size) +} /* end H5F_sieve_buf_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_gc_ref + * + * Purpose: Replaced a macro to retrieve the "garbage collect + * references flag" now that the generic properties are being used + * to store the values. + * + * Return: Success: The "garbage collect references flag" + * is returned. + * + * Failure: (should not happen) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jul 8 2005 + * + *------------------------------------------------------------------------- + */ +unsigned +H5F_gc_ref(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_gc_ref) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->gc_ref) +} /* end H5F_gc_ref() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_use_latest_format + * + * Purpose: Retrieve the 'use the latest version of the format' flag for + * the file. + * + * Return: Success: Non-negative, the 'use the latest format' flag + * + * Failure: (can't happen) + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Oct 2 2006 + * + *------------------------------------------------------------------------- + */ +hbool_t +H5F_use_latest_format(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_use_latest_format) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->latest_format) +} /* end H5F_use_latest_format() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_fc_degree + * + * Purpose: Retrieve the 'file close degree' for the file. + * + * Return: Success: Non-negative, the 'file close degree' + * + * Failure: (can't happen) + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Mar 5 2007 + * + *------------------------------------------------------------------------- + */ +H5F_close_degree_t +H5F_get_fc_degree(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fc_degree) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->fc_degree) +} /* end H5F_get_fc_degree() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_store_msg_crt_idx + * + * Purpose: Retrieve the 'store message creation index' flag for the file. + * + * Return: Success: Non-negative, the 'store message creation index' flag + * + * Failure: (can't happen) + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Mar 6 2007 + * + *------------------------------------------------------------------------- + */ +hbool_t +H5F_store_msg_crt_idx(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_store_msg_crt_idx) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->store_msg_crt_idx) +} /* end H5F_store_msg_crt_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_has_feature + * + * Purpose: Check if a file has a particular feature enabled + * + * Return: Success: Non-negative - TRUE or FALSE + * Failure: Negative (should not happen) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 31 2004 + * + *------------------------------------------------------------------------- + */ +hbool_t +H5F_has_feature(const H5F_t *f, unsigned feature) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_has_feature) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI((hbool_t)(f->shared->lf->feature_flags&feature)) +} /* end H5F_has_feature() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_driver_id + * + * Purpose: Quick and dirty routine to retrieve the file's 'driver_id' value + * (Mainly added to stop non-file routines from poking about in the + * H5F_t data structure) + * + * Return: 'driver_id' on success/abort on failure (shouldn't fail) + * + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * October 10, 2000 + * + *------------------------------------------------------------------------- + */ +hid_t +H5F_get_driver_id(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_driver_id) + + HDassert(f); + HDassert(f->shared); + HDassert(f->shared->lf); + + FUNC_LEAVE_NOAPI(f->shared->lf->driver_id) +} /* end H5F_get_driver_id() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_fileno + * + * Purpose: Quick and dirty routine to retrieve the file's 'fileno' value + * (Mainly added to stop non-file routines from poking about in the + * H5F_t data structure) + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * March 27, 2002 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_get_fileno(const H5F_t *f, unsigned long *filenum) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5F_get_fileno, FAIL) + + 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) + HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_fileno() */ + diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index 5036a4f..6196557 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -31,6 +31,7 @@ #include "H5Fpkg.h" /* File access */ #include "H5FDprivate.h" /* File drivers */ #include "H5Iprivate.h" /* IDs */ +#include "H5MFprivate.h" /* File memory management */ #include "H5Pprivate.h" /* Property lists */ #include "H5SMprivate.h" /* Shared Object Header Messages */ @@ -186,9 +187,9 @@ H5F_locate_signature(H5FD_t *file, hid_t dxpl_id) */ for(n = 8; n < maxpow; n++) { addr = (8 == n) ? 0 : (haddr_t)1 << n; - if(H5FD_set_eoa(file, H5FD_MEM_SUPER, addr+H5F_SIGNATURE_LEN) < 0) + if(H5FD_set_eoa(file, H5FD_MEM_SUPER, addr + H5F_SIGNATURE_LEN) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, HADDR_UNDEF, "unable to set EOA value for file signature") - if(H5FD_read(file, H5FD_MEM_SUPER, dxpl_id, addr, (size_t)H5F_SIGNATURE_LEN, buf) < 0) + if(H5FD_read(file, dxpl_id, H5FD_MEM_SUPER, addr, (size_t)H5F_SIGNATURE_LEN, buf) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, HADDR_UNDEF, "unable to read file signature") if(!HDmemcmp(buf, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN)) break; @@ -235,6 +236,7 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) H5P_genplist_t *c_plist; /* File creation property list */ H5F_file_t *shared; /* shared part of `file' */ H5FD_t *lf; /* file driver part of `shared' */ + haddr_t abs_super_addr; /* Absolute offset of superblock in file */ haddr_t stored_eoa; /*relative end-of-addr in file */ haddr_t eof; /*end of file address */ size_t sizeof_addr; /* Size of offsets in the file (in bytes) */ @@ -256,14 +258,14 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") /* Find the superblock */ - if(HADDR_UNDEF == (shared->super_addr = H5F_locate_signature(lf, dxpl_id))) + if(HADDR_UNDEF == (abs_super_addr = H5F_locate_signature(lf, dxpl_id))) HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to find file signature") /* Read fixed-size portion of the superblock */ p = sbuf; - if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->super_addr + fixed_size) < 0) + if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, abs_super_addr + fixed_size) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed") - if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr, fixed_size, p) < 0) + if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, abs_super_addr, fixed_size, p) < 0) HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "unable to read superblock") /* Skip over signature (already checked when locating the superblock) */ @@ -285,9 +287,9 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) HDassert(fixed_size + variable_size <= sizeof(sbuf)); /* Read in variable-sized portion of superblock */ - if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->super_addr + fixed_size + variable_size) < 0) + if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, abs_super_addr + fixed_size + variable_size) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed") - if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr + fixed_size, variable_size, p) < 0) + if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, abs_super_addr + fixed_size, variable_size, p) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read superblock") /* Check for older version of superblock format */ @@ -388,17 +390,23 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) * Check if superblock address is different from base address and * adjust base address and "end of address" address if so. */ - if(!H5F_addr_eq(shared->super_addr, shared->base_addr)) { + if(!H5F_addr_eq(abs_super_addr, shared->base_addr)) { /* Check if the superblock moved earlier in the file */ - if(H5F_addr_lt(shared->super_addr, shared->base_addr)) - stored_eoa -= (shared->base_addr - shared->super_addr); + if(H5F_addr_lt(abs_super_addr, shared->base_addr)) + stored_eoa -= (shared->base_addr - abs_super_addr); else /* The superblock moved later in the file */ - stored_eoa += (shared->super_addr - shared->base_addr); + stored_eoa += (abs_super_addr - shared->base_addr); - shared->base_addr = shared->super_addr; + shared->base_addr = abs_super_addr; } /* end if */ + /* Set the base address for the file in the VFD now, after adjusting + * space for possible offsets of the HDF5 data in the file. + */ + if(H5FD_set_base_addr(lf, shared->base_addr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set base address for file driver") + /* This step is for h5repart tool only. If user wants to change file driver * from family to sec2 while using h5repart, set the driver address to * undefined to let the library ignore the family driver information saved @@ -412,14 +420,13 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Buffer for driver info block */ char drv_name[9]; /* Name of driver */ unsigned drv_vers; /* Version of driver info block */ - haddr_t drv_addr = shared->base_addr + shared->driver_addr; size_t drv_variable_size; /* Size of variable-length portion of driver info block, in bytes */ /* Read in fixed-sized portion of driver info block */ p = dbuf; - if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, drv_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < 0) + if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed") - if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr, (size_t)H5F_DRVINFOBLOCK_HDR_SIZE, p) < 0) + if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, shared->driver_addr, (size_t)H5F_DRVINFOBLOCK_HDR_SIZE, p) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read driver information block") /* Version number */ @@ -449,9 +456,9 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "multi driver should be used") /* Read in variable-sized portion of driver info block */ - if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, drv_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drv_variable_size) < 0) + if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drv_variable_size) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed") - if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr + H5F_DRVINFOBLOCK_HDR_SIZE, drv_variable_size, p) < 0) + if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, shared->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE, drv_variable_size, p) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read file driver information") /* Decode driver information */ @@ -512,16 +519,22 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) * Check if superblock address is different from base address and * adjust base address and "end of address" address if so. */ - if(!H5F_addr_eq(shared->super_addr, shared->base_addr)) { + if(!H5F_addr_eq(abs_super_addr, shared->base_addr)) { /* Check if the superblock moved earlier in the file */ - if(H5F_addr_lt(shared->super_addr, shared->base_addr)) - stored_eoa -= (shared->base_addr - shared->super_addr); + if(H5F_addr_lt(abs_super_addr, shared->base_addr)) + stored_eoa -= (shared->base_addr - abs_super_addr); else /* The superblock moved later in the file */ - stored_eoa += (shared->super_addr - shared->base_addr); + stored_eoa += (abs_super_addr - shared->base_addr); - shared->base_addr = shared->super_addr; + shared->base_addr = abs_super_addr; } /* end if */ + + /* Set the base address for the file in the VFD now, after adjusting + * space for possible offsets of the HDF5 data in the file. + */ + if(H5FD_set_base_addr(lf, shared->base_addr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set base address for file driver") } /* end else */ /* @@ -538,7 +551,8 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) */ if(HADDR_UNDEF == (eof = H5FD_get_eof(lf))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size") - if(eof < stored_eoa) + /* (Account for the stored EOA being absolute offset -QAK) */ + if((eof + H5F_BASE_ADDR(f)) < stored_eoa) HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, FAIL, "truncated file") /* @@ -652,9 +666,8 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id) { H5P_genplist_t *plist; /* File creation property list */ hsize_t userblock_size; /* Size of userblock, in bytes */ - size_t superblock_size; /* Size of superblock, in bytes */ + hsize_t superblock_size; /* Size of superblock, in bytes */ size_t driver_size; /* Size of driver info block (bytes) */ - hsize_t alloc_size; /* Size to allocate on disk */ unsigned super_vers; /* Superblock version */ haddr_t super_addr; /* Address of superblock */ hbool_t need_ext; /* Whether the superblock extension is needed */ @@ -674,10 +687,19 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id) */ if(H5P_get(plist, H5F_CRT_USER_BLOCK_NAME, &userblock_size) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get userblock size") - f->shared->super_addr = userblock_size; - f->shared->base_addr = f->shared->super_addr; + f->shared->base_addr = userblock_size; f->shared->status_flags = 0; + /* Reserve space for the userblock */ + if(H5FD_set_eoa(f->shared->lf, H5FD_MEM_SUPER, userblock_size) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set EOA value for userblock") + + /* Set the base address for the file in the VFD now, after allocating + * space for userblock. + */ + if(H5FD_set_base_addr(f->shared->lf, f->shared->base_addr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set base address for file driver") + /* Grab superblock version from property list */ if(H5P_get(plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get superblock version") @@ -703,11 +725,9 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id) * superblock need to be at the beginning of the file and only the first * allocation request is required to return memory at format address zero. */ - H5_CHECK_OVERFLOW(f->shared->base_addr, haddr_t, hsize_t); - alloc_size = (hsize_t)f->shared->base_addr + superblock_size; if(super_vers < HDF5_SUPERBLOCK_VERSION_2) - alloc_size += driver_size; - super_addr = H5FD_alloc(f->shared->lf, H5FD_MEM_SUPER, dxpl_id, alloc_size); + superblock_size += driver_size; + super_addr = H5MF_alloc(f, H5FD_MEM_SUPER, dxpl_id, superblock_size); if(HADDR_UNDEF == super_addr) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to allocate file space for userblock and/or superblock") if(0 != super_addr) @@ -836,6 +856,7 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id) H5P_genplist_t *plist; /* File creation property list */ uint8_t buf[H5F_MAX_SUPERBLOCK_SIZE + H5F_MAX_DRVINFOBLOCK_SIZE]; /* Superblock & driver info blockencoding buffer */ uint8_t *p; /* Ptr into encoding buffer */ + haddr_t rel_eoa; /* Relative EOA for file */ size_t superblock_size; /* Size of superblock, in bytes */ size_t driver_size; /* Size of driver info block (bytes)*/ unsigned super_vers; /* Superblock version */ @@ -886,7 +907,8 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id) H5F_addr_encode(f, &p, f->shared->base_addr); H5F_addr_encode(f, &p, f->shared->extension_addr); - H5F_addr_encode(f, &p, H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER)); + rel_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER); + H5F_addr_encode(f, &p, (rel_eoa + f->shared->base_addr)); H5F_addr_encode(f, &p, f->shared->driver_addr); if(H5G_obj_ent_encode(f, &p, H5G_oloc(f->shared->root_grp)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode root group information") @@ -932,7 +954,8 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id) /* Base, superblock extension & end of file addresses */ H5F_addr_encode(f, &p, f->shared->base_addr); H5F_addr_encode(f, &p, f->shared->extension_addr); - H5F_addr_encode(f, &p, H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER)); + rel_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER); + H5F_addr_encode(f, &p, (rel_eoa + f->shared->base_addr)); /* Retrieve information for root group */ if(NULL == (root_oloc = H5G_oloc(f->shared->root_grp))) @@ -957,8 +980,8 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id) /* Double check we didn't overrun the block (unlikely) */ HDassert(superblock_size <= sizeof(buf)); - /* Write superblock */ - if(H5FD_write(f->shared->lf, H5FD_MEM_SUPER, dxpl_id, f->shared->super_addr, superblock_size, buf) < 0) + /* Write superblock (always at relative offset 0) */ + if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_SUPER, (haddr_t)0, superblock_size, buf) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write superblock") done: @@ -429,8 +429,9 @@ done: hid_t H5Gget_create_plist(hid_t group_id) { - htri_t ginfo_exists = 0; - htri_t linfo_exists = 0; + H5O_linfo_t linfo; /* Link info message */ + htri_t ginfo_exists; + htri_t linfo_exists; H5G_t *grp = NULL; H5P_genplist_t *gcpl_plist; H5P_genplist_t *new_plist; @@ -472,15 +473,9 @@ H5Gget_create_plist(hid_t group_id) } /* end if */ /* Check for the group having a link info message */ - if((linfo_exists = H5O_msg_exists(&(grp->oloc), H5O_LINFO_ID, H5AC_ind_dxpl_id)) < 0) + if((linfo_exists = H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_ind_dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header") if(linfo_exists) { - H5O_linfo_t linfo; /* Link info message */ - - /* Read the link info */ - if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_ind_dxpl_id)) - HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info") - /* Set the link info for the property list */ if(H5P_set(new_plist, H5G_CRT_LINK_INFO_NAME, &linfo) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set link info") @@ -1828,6 +1823,7 @@ H5G_visit_cb(const H5O_link_t *lnk, void *_udata) 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 */ + htri_t linfo_exists; /* Whether the link info message exists */ /* Add the path separator to the current path */ HDassert(udata->path[udata->curr_path_len] == '\0'); @@ -1835,7 +1831,9 @@ H5G_visit_cb(const H5O_link_t *lnk, void *_udata) udata->curr_path_len++; /* Attempt to get the link info for this group */ - if(H5G_obj_get_linfo(&obj_oloc, &linfo, udata->dxpl_id)) { + if((linfo_exists = H5G_obj_get_linfo(&obj_oloc, &linfo, udata->dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "can't check for link info message") + if(linfo_exists) { /* Check for creation order tracking, if creation order index lookup requested */ if(idx_type == H5_INDEX_CRT_ORDER) { /* Check if creation order is tracked */ @@ -1847,9 +1845,6 @@ H5G_visit_cb(const H5O_link_t *lnk, void *_udata) 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 */ @@ -1918,6 +1913,7 @@ H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type, { H5G_iter_visit_ud_t udata; /* User data for callback */ H5O_linfo_t linfo; /* Link info message */ + htri_t linfo_exists; /* Whether the link info message exists */ hid_t gid = (-1); /* Group ID */ H5G_t *grp = NULL; /* Group opened */ H5G_loc_t loc; /* Location of group passed in */ @@ -1987,7 +1983,9 @@ H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type, } /* end if */ /* Attempt to get the link info for this group */ - if(H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) { + if((linfo_exists = H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message") + if(linfo_exists) { /* Check for creation order tracking, if creation order index lookup requested */ if(idx_type == H5_INDEX_CRT_ORDER) { /* Check if creation order is tracked */ @@ -1999,9 +1997,6 @@ H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type, 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 */ diff --git a/src/H5Gcache.c b/src/H5Gcache.c new file mode 100644 index 0000000..0e2a699 --- /dev/null +++ b/src/H5Gcache.c @@ -0,0 +1,470 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5Gcache.c + * Feb 5 2008 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: Implement group metadata cache methods. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Gpkg.h" /* Groups */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5WBprivate.h" /* Wrapped Buffers */ + + +/****************/ +/* Local Macros */ +/****************/ + +#define H5G_NODE_VERS 1 /* Symbol table node version number */ +#define H5G_NODE_BUF_SIZE 512 /* Size of stack buffer for serialized nodes */ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Metadata cache (H5AC) callbacks */ +static H5G_node_t *H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1, + void *_udata2); +static herr_t H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, + H5G_node_t *sym, unsigned UNUSED * flags_ptr); +static herr_t H5G_node_dest(H5F_t *f, H5G_node_t *sym); +static herr_t H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy); +static herr_t H5G_node_size(const H5F_t *f, const H5G_node_t *sym, size_t *size_ptr); + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Symbol table nodes inherit cache-like properties from H5AC */ +const H5AC_class_t H5AC_SNODE[1] = {{ + H5AC_SNODE_ID, + (H5AC_load_func_t)H5G_node_load, + (H5AC_flush_func_t)H5G_node_flush, + (H5AC_dest_func_t)H5G_node_dest, + (H5AC_clear_func_t)H5G_node_clear, + (H5AC_size_func_t)H5G_node_size, +}}; + + +/* Declare extern the free list to manage the H5G_node_t struct */ +H5FL_EXTERN(H5G_node_t); + +/* Declare extern the free list to manage sequences of H5G_entry_t's */ +H5FL_SEQ_EXTERN(H5G_entry_t); + + +/*------------------------------------------------------------------------- + * Function: H5G_node_load + * + * Purpose: Loads a symbol table node from the file. + * + * Return: Success: Ptr to the new table. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 23 1997 + * + * Modifications: + * Robb Matzke, 1999-07-28 + * The ADDR argument is passed by value. + * + * Quincey Koziol, 2002-7-180 + * Added dxpl parameter to allow more control over I/O from metadata + * cache. + *------------------------------------------------------------------------- + */ +static H5G_node_t * +H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_udata1, + void UNUSED * _udata2) +{ + H5G_node_t *sym = NULL; + size_t size; + H5WB_t *wb = NULL; /* Wrapped buffer for node data */ + uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */ + uint8_t *node; /* Pointer to node buffer */ + const uint8_t *p; + H5G_node_t *ret_value; /*for error handling */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_node_load) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(!_udata1); + HDassert(NULL == _udata2); + + /* + * Initialize variables. + */ + + /* Wrap the local buffer for serialized node info */ + if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf)))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't wrap buffer") + + /* Compute the size of the serialized symbol table node on disk */ + size = H5G_node_size_real(f); + + /* Get a pointer to a buffer that's large enough for node */ + if(NULL == (node = (uint8_t *)H5WB_actual(wb, size))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't get actual buffer") + + /* Read the serialized symbol table node. */ + if(H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0) + HGOTO_ERROR(H5E_SYM, H5E_READERROR, NULL, "unable to read symbol table node") + + /* Get temporary pointer to serialized node */ + p = node; + + /* magic */ + if(HDmemcmp(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node signature") + p += 4; + + /* version */ + if(H5G_NODE_VERS != *p++) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node version") + + /* reserved */ + p++; + + /* Allocate symbol table data structures */ + if(NULL == (sym = H5FL_CALLOC(H5G_node_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + if(NULL == (sym->entry = H5FL_SEQ_CALLOC(H5G_entry_t, (size_t)(2 * H5F_SYM_LEAF_K(f))))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* number of symbols */ + UINT16DECODE(p, sym->nsyms); + + /* entries */ + if(H5G_ent_decode_vec(f, &p, sym->entry, sym->nsyms) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "unable to decode symbol table entries") + + /* Set return value */ + ret_value = sym; + +done: + /* Release resources */ + if(wb && H5WB_unwrap(wb) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "can't close wrapped buffer") + if(!ret_value) + if(sym && H5G_node_dest(f, sym) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, NULL, "unable to destroy symbol table node") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_node_load() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_node_flush + * + * Purpose: Flush a symbol table node to disk. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 23 1997 + * + * Modifications: + * rky, 1998-08-28 + * Only p0 writes metadata to disk. + * + * Robb Matzke, 1999-07-28 + * The ADDR argument is passed by value. + * + * Quincey Koziol, 2002-7-180 + * Added dxpl parameter to allow more control over I/O from metadata + * cache. + * + * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 + * Added `id to name' support. + * + * JRM -- 8/21/06 + * Added the flags_ptr parameter. This parameter exists to + * allow the flush routine to report to the cache if the + * entry is resized or renamed as a result of the flush. + * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_t *sym, unsigned UNUSED * flags_ptr) +{ + H5WB_t *wb = NULL; /* Wrapped buffer for node data */ + uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */ + unsigned u; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_node_flush) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(sym); + + /* + * Look for dirty entries and set the node dirty flag. + */ + for(u = 0; u < sym->nsyms; u++) + if(sym->entry[u].dirty) { + /* Set the node's dirty flag */ + sym->cache_info.is_dirty = TRUE; + + /* Reset the entry's dirty flag */ + sym->entry[u].dirty = FALSE; + } /* end if */ + + /* + * Write the symbol node to disk. + */ + if(sym->cache_info.is_dirty) { + uint8_t *node; /* Pointer to node buffer */ + uint8_t *p; /* Pointer into raw data buffer */ + size_t size; + + /* Wrap the local buffer for serialized node info */ + if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf)))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't wrap buffer") + + /* Compute the size of the serialized symbol table node on disk */ + size = H5G_node_size_real(f); + + /* Get a pointer to a buffer that's large enough for node */ + if(NULL == (node = (uint8_t *)H5WB_actual(wb, size))) + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer") + + /* Get temporary pointer to serialized symbol table node */ + p = node; + + /* magic number */ + HDmemcpy(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC); + p += 4; + + /* version number */ + *p++ = H5G_NODE_VERS; + + /* reserved */ + *p++ = 0; + + /* number of symbols */ + UINT16ENCODE(p, sym->nsyms); + + /* entries */ + if(H5G_ent_encode_vec(f, &p, sym->entry, sym->nsyms) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't serialize") + HDmemset(p, 0, size - (p - node)); + + /* Write the serialized symbol table node. */ + if(H5F_block_write(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0) + HGOTO_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "unable to write symbol table node to the file") + + /* Reset the node's dirty flag */ + sym->cache_info.is_dirty = FALSE; + } /* end if */ + + /* + * Destroy the symbol node? This might happen if the node is being + * preempted from the cache. + */ + if(destroy) + if(H5G_node_dest(f, sym) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node") + +done: + /* Release resources */ + if(wb && H5WB_unwrap(wb) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_node_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_node_dest + * + * Purpose: Destroy a symbol table node in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 15 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_node_dest(H5F_t *f, H5G_node_t *sym) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_node_dest) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(sym); + + /* Verify that node is clean */ + HDassert(sym->cache_info.is_dirty == FALSE); + + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!sym->cache_info.free_file_space_on_destroy || H5F_addr_defined(sym->cache_info.addr)); + + /* Check for freeing file space for symbol table node */ + if(sym->cache_info.free_file_space_on_destroy) { + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, sym->cache_info.addr, (hsize_t)H5G_node_size_real(f)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to free symbol table node") + } /* end if */ + + /* Release resources */ + if(sym->entry) + sym->entry = (H5G_entry_t *)H5FL_SEQ_FREE(H5G_entry_t, sym->entry); + (void)H5FL_FREE(H5G_node_t, sym); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_node_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_node_clear + * + * Purpose: Mark a symbol table node in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 20 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy) +{ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5G_node_clear); + + /* + * Check arguments. + */ + assert(sym); + + /* Look for dirty entries and reset their dirty flag. */ + for(u = 0; u < sym->nsyms; u++) + sym->entry[u].dirty=FALSE; + sym->cache_info.is_dirty = FALSE; + + /* + * Destroy the symbol node? This might happen if the node is being + * preempted from the cache. + */ + if (destroy) + if (H5G_node_dest(f, sym) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5G_node_clear() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_node_size + * + * Purpose: Compute the size in bytes of the specified instance of + * H5G_node_t on disk, and return it in *size_ptr. On failure + * the value of size_ptr is undefined. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/13/04 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_node_size(const H5F_t *f, const H5G_node_t UNUSED *sym, size_t *size_ptr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_size); + + /* + * Check arguments. + */ + HDassert(f); + HDassert(size_ptr); + + *size_ptr = H5G_node_size_real(f); + + FUNC_LEAVE_NOAPI(SUCCEED); +} /* H5G_node_size() */ + diff --git a/src/H5Gcompact.c b/src/H5Gcompact.c index 6b41007..9ecd6c1 100644 --- a/src/H5Gcompact.c +++ b/src/H5Gcompact.c @@ -489,7 +489,7 @@ done: * * Purpose: Look up an object relative to a group, using link messages. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative (TRUE/FALSE) on success/Negative on failure * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu @@ -497,13 +497,13 @@ done: * *------------------------------------------------------------------------- */ -herr_t +htri_t H5G_compact_lookup(H5O_loc_t *oloc, const char *name, H5O_link_t *lnk, hid_t dxpl_id) { H5G_iter_lkp_t udata; /* User data for iteration callback */ H5O_mesg_operator_t op; /* Message operator */ - herr_t ret_value = SUCCEED; /* Return value */ + htri_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_compact_lookup, FAIL) @@ -522,9 +522,8 @@ H5G_compact_lookup(H5O_loc_t *oloc, const char *name, H5O_link_t *lnk, if(H5O_msg_iterate(oloc, H5O_LINK_ID, &op, &udata, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over link messages") - /* Check if we found the link we were looking for */ - if(!udata.found) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") + /* Determine if we found the link we were looking for */ + ret_value = udata.found; done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5Gdense.c b/src/H5Gdense.c index a15d961..6c3a171 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -490,7 +490,7 @@ done: * * Purpose: Look up a link within a group that uses dense link storage * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative (TRUE/FALSE) on success/Negative on failure * * Programmer: Quincey Koziol * koziol@hdfgroup.org @@ -498,13 +498,13 @@ done: * *------------------------------------------------------------------------- */ -herr_t +htri_t H5G_dense_lookup(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, const char *name, H5O_link_t *lnk) { H5G_bt2_ud_common_t udata; /* User data for v2 B-tree link lookup */ H5HF_t *fheap = NULL; /* Fractal heap handle */ - herr_t ret_value = SUCCEED; /* Return value */ + htri_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_dense_lookup, FAIL) @@ -530,7 +530,7 @@ H5G_dense_lookup(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, udata.found_op_data = lnk; /* Find & copy the named link in the 'name' index */ - if(H5B2_find(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &udata, NULL, NULL) < 0) + if((ret_value = H5B2_find(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &udata, NULL, NULL)) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to locate link in name index") done: diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c index 6a4310f..ddb5dfe 100644 --- a/src/H5Gdeprec.c +++ b/src/H5Gdeprec.c @@ -1136,6 +1136,7 @@ static H5G_obj_t H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id) { H5O_linfo_t linfo; /* Link info message */ + htri_t linfo_exists; /* Whether the link info message exists */ H5G_obj_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_obj_get_type_by_idx, H5G_UNKNOWN) @@ -1144,7 +1145,9 @@ H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id) HDassert(oloc); /* Attempt to get the link info for this group */ - if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) { + if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5G_UNKNOWN, "can't check for link info message") + if(linfo_exists) { if(H5F_addr_defined(linfo.fheap_addr)) { /* Get the object's name from the dense link storage */ if((ret_value = H5G_dense_get_type_by_idx(oloc->file, dxpl_id, &linfo, idx)) < 0) @@ -1157,9 +1160,6 @@ H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id) } /* end else */ } /* end if */ else { - /* Clear error stack from not finding the link info message */ - H5E_clear_stack(NULL); - /* Get the object's type from the symbol table */ if((ret_value = H5G_stab_get_type_by_idx(oloc, idx, dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "can't locate type") diff --git a/src/H5Gnode.c b/src/H5Gnode.c index cefed5b..9468302 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -39,7 +39,6 @@ #include "H5HLprivate.h" /* Local Heaps */ #include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ -#include "H5WBprivate.h" /* Wrapped Buffers */ /* Private typedefs */ @@ -51,38 +50,11 @@ typedef struct H5G_node_key_t { size_t offset; /*offset into heap for name */ } H5G_node_key_t; -/* - * A symbol table node is a collection of symbol table entries. It can - * be thought of as the lowest level of the B-link tree that points to - * a collection of symbol table entries that belong to a specific symbol - * table or group. - */ -typedef struct H5G_node_t { - H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */ - /* first field in structure */ - unsigned nsyms; /*number of symbols */ - H5G_entry_t *entry; /*array of symbol table entries */ -} H5G_node_t; - /* Private macros */ -#define H5G_NODE_VERS 1 /*symbol table node version number */ -#define H5G_NODE_SIZEOF_HDR(F) (H5_SIZEOF_MAGIC + 4) -/* Size of stack buffer for serialized nodes */ -#define H5G_NODE_BUF_SIZE 512 +#define H5G_NODE_SIZEOF_HDR(F) (H5_SIZEOF_MAGIC + 4) /* PRIVATE PROTOTYPES */ -static herr_t H5G_node_serialize(H5F_t *f, H5G_node_t *sym, size_t size, uint8_t *buf); -static size_t H5G_node_size_real(const H5F_t *f); - -/* Metadata cache callbacks */ -static H5G_node_t *H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1, - void *_udata2); -static herr_t H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, - H5G_node_t *sym, unsigned UNUSED * flags_ptr); -static herr_t H5G_node_dest(H5F_t *f, H5G_node_t *sym); -static herr_t H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy); -static herr_t H5G_node_size(const H5F_t *f, const H5G_node_t *sym, size_t *size_ptr); /* B-tree callbacks */ static H5RC_t *H5G_node_get_shared(const H5F_t *f, const void *_udata); @@ -93,7 +65,7 @@ static int H5G_node_cmp2(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata, void *_rt_key); static int H5G_node_cmp3(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata, void *_rt_key); -static herr_t H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key, +static htri_t H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key, void *_udata); static H5B_ins_t H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key, hbool_t *lt_key_changed, void *_md_key, @@ -111,16 +83,6 @@ static herr_t H5G_node_debug_key(FILE *stream, H5F_t *f, hid_t dxpl_id, int indent, int fwidth, const void *key, const void *udata); -/* H5G inherits cache-like properties from H5AC */ -const H5AC_class_t H5AC_SNODE[1] = {{ - H5AC_SNODE_ID, - (H5AC_load_func_t)H5G_node_load, - (H5AC_flush_func_t)H5G_node_flush, - (H5AC_dest_func_t)H5G_node_dest, - (H5AC_clear_func_t)H5G_node_clear, - (H5AC_size_func_t)H5G_node_size, -}}; - /* H5G inherits B-tree like properties from H5B */ H5B_class_t H5B_SNODE[1] = {{ H5B_SNODE_ID, /*id */ @@ -140,10 +102,10 @@ H5B_class_t H5B_SNODE[1] = {{ }}; /* Declare a free list to manage the H5G_node_t struct */ -H5FL_DEFINE_STATIC(H5G_node_t); +H5FL_DEFINE(H5G_node_t); /* Declare a free list to manage sequences of H5G_entry_t's */ -H5FL_SEQ_DEFINE_STATIC(H5G_entry_t); +H5FL_SEQ_DEFINE(H5G_entry_t); /*------------------------------------------------------------------------- @@ -303,7 +265,7 @@ H5G_node_debug_key(FILE *stream, H5F_t *f, hid_t UNUSED dxpl_id, int indent, * *------------------------------------------------------------------------- */ -static size_t +size_t H5G_node_size_real(const H5F_t *f) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_size_real); @@ -314,389 +276,6 @@ H5G_node_size_real(const H5F_t *f) /*------------------------------------------------------------------------- - * Function: H5G_node_load - * - * Purpose: Loads a symbol table node from the file. - * - * Return: Success: Ptr to the new table. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jun 23 1997 - * - * Modifications: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - *------------------------------------------------------------------------- - */ -static H5G_node_t * -H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_udata1, - void UNUSED * _udata2) -{ - H5G_node_t *sym = NULL; - size_t size; - H5WB_t *wb = NULL; /* Wrapped buffer for node data */ - uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */ - uint8_t *node; /* Pointer to node buffer */ - const uint8_t *p; - H5G_node_t *ret_value; /*for error handling */ - - FUNC_ENTER_NOAPI_NOINIT(H5G_node_load) - - /* - * Check arguments. - */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); - HDassert(!_udata1); - HDassert(NULL == _udata2); - - /* - * Initialize variables. - */ - - /* Wrap the local buffer for serialized node info */ - if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf)))) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't wrap buffer") - - /* Compute the size of the serialized symbol table node on disk */ - size = H5G_node_size_real(f); - - /* Get a pointer to a buffer that's large enough for node */ - if(NULL == (node = (uint8_t *)H5WB_actual(wb, size))) - HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't get actual buffer") - - /* Read the serialized symbol table node. */ - if(H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0) - HGOTO_ERROR(H5E_SYM, H5E_READERROR, NULL, "unable to read symbol table node") - - /* Get temporary pointer to serialized node */ - p = node; - - /* magic */ - if(HDmemcmp(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC)) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node signature") - p += H5_SIZEOF_MAGIC; - - /* version */ - if(H5G_NODE_VERS != *p++) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node version") - - /* reserved */ - p++; - - /* Allocate symbol table data structures */ - if(NULL == (sym = H5FL_CALLOC(H5G_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - if(NULL == (sym->entry = H5FL_SEQ_CALLOC(H5G_entry_t, (size_t)(2 * H5F_SYM_LEAF_K(f))))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - - /* number of symbols */ - UINT16DECODE(p, sym->nsyms); - - /* entries */ - if(H5G_ent_decode_vec(f, &p, sym->entry, sym->nsyms) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "unable to decode symbol table entries") - - /* Set return value */ - ret_value = sym; - -done: - /* Release resources */ - if(wb && H5WB_unwrap(wb) < 0) - HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "can't close wrapped buffer") - if(!ret_value) - if(sym && H5G_node_dest(f, sym) < 0) - HDONE_ERROR(H5E_SYM, H5E_CANTFREE, NULL, "unable to destroy symbol table node") - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_node_load() */ - - -/*------------------------------------------------------------------------- - * Function: H5G_node_flush - * - * Purpose: Flush a symbol table node to disk. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jun 23 1997 - * - * Modifications: - * rky, 1998-08-28 - * Only p0 writes metadata to disk. - * - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 - * Added `id to name' support. - * - * JRM -- 8/21/06 - * Added the flags_ptr parameter. This parameter exists to - * allow the flush routine to report to the cache if the - * entry is resized or renamed as a result of the flush. - * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. - * - *------------------------------------------------------------------------- - */ -static herr_t -H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_t *sym, unsigned UNUSED * flags_ptr) -{ - H5WB_t *wb = NULL; /* Wrapped buffer for node data */ - uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */ - unsigned u; - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5G_node_flush) - - /* - * Check arguments. - */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); - HDassert(sym); - - /* - * Look for dirty entries and set the node dirty flag. - */ - for(u = 0; u < sym->nsyms; u++) - if(sym->entry[u].dirty) { - /* Set the node's dirty flag */ - sym->cache_info.is_dirty = TRUE; - - /* Reset the entry's dirty flag */ - sym->entry[u].dirty = FALSE; - } /* end if */ - - /* - * Write the symbol node to disk. - */ - if(sym->cache_info.is_dirty) { - uint8_t *node; /* Pointer to node buffer */ - size_t size; - - /* Wrap the local buffer for serialized node info */ - if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf)))) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't wrap buffer") - - /* Compute the size of the serialized symbol table node on disk */ - size = H5G_node_size_real(f); - - /* Get a pointer to a buffer that's large enough for node */ - if(NULL == (node = (uint8_t *)H5WB_actual(wb, size))) - HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer") - - /* Serialize symbol table node into buffer */ - if(H5G_node_serialize(f, sym, size, node) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTSERIALIZE, FAIL, "node serialization failed") - - /* Write the serialized symbol table node. */ - if(H5F_block_write(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0) - HGOTO_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "unable to write symbol table node to the file") - - /* Reset the node's dirty flag */ - sym->cache_info.is_dirty = FALSE; - } /* end if */ - - /* - * Destroy the symbol node? This might happen if the node is being - * preempted from the cache. - */ - if(destroy) - if(H5G_node_dest(f, sym) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node") - -done: - /* Release resources */ - if(wb && H5WB_unwrap(wb) < 0) - HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer") - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_node_flush() */ - - -/*------------------------------------------------------------------------- - * Function: H5G_node_serialize - * - * Purpose: Serialize the symbol table node - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Bill Wendling - * wendling@ncsa.uiuc.edu - * Sept. 16, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5G_node_serialize(H5F_t *f, H5G_node_t *sym, size_t size, uint8_t *buf) -{ - uint8_t *p; - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5G_node_serialize); - - /* check args */ - assert(f); - assert(sym); - assert(buf); - - p = buf; - - /* magic number */ - HDmemcpy(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC); - p += H5_SIZEOF_MAGIC; - - /* version number */ - *p++ = H5G_NODE_VERS; - - /* reserved */ - *p++ = 0; - - /* number of symbols */ - UINT16ENCODE(p, sym->nsyms); - - /* entries */ - if (H5G_ent_encode_vec(f, &p, sym->entry, sym->nsyms) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't serialize") - HDmemset(p, 0, size - (p - buf)); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_node_dest - * - * Purpose: Destroy a symbol table node in memory. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jan 15 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5G_node_dest(H5F_t UNUSED *f, H5G_node_t *sym) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_dest) - - /* - * Check arguments. - */ - HDassert(sym); - - /* Verify that node is clean */ - HDassert(sym->cache_info.is_dirty == FALSE); - - if(sym->entry) - sym->entry = (H5G_entry_t *)H5FL_SEQ_FREE(H5G_entry_t, sym->entry); - (void)H5FL_FREE(H5G_node_t, sym); - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5G_node_dest() */ - - -/*------------------------------------------------------------------------- - * Function: H5G_node_clear - * - * Purpose: Mark a symbol table node in memory as non-dirty. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 20 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy) -{ - unsigned u; /* Local index variable */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5G_node_clear); - - /* - * Check arguments. - */ - assert(sym); - - /* Look for dirty entries and reset their dirty flag. */ - for(u = 0; u < sym->nsyms; u++) - sym->entry[u].dirty=FALSE; - sym->cache_info.is_dirty = FALSE; - - /* - * Destroy the symbol node? This might happen if the node is being - * preempted from the cache. - */ - if (destroy) - if (H5G_node_dest(f, sym) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5G_node_clear() */ - - -/*------------------------------------------------------------------------- - * Function: H5G_node_size - * - * Purpose: Compute the size in bytes of the specified instance of - * H5G_node_t on disk, and return it in *size_ptr. On failure - * the value of size_ptr is undefined. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: John Mainzer - * 5/13/04 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5G_node_size(const H5F_t *f, const H5G_node_t UNUSED *sym, size_t *size_ptr) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_size); - - /* - * Check arguments. - */ - HDassert(f); - HDassert(size_ptr); - - *size_ptr = H5G_node_size_real(f); - - FUNC_LEAVE_NOAPI(SUCCEED); -} /* H5G_node_size() */ - - -/*------------------------------------------------------------------------- * Function: H5G_node_create * * Purpose: Creates a new empty symbol table node. This function is @@ -903,8 +482,8 @@ H5G_node_cmp3(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata, * entry field. Otherwise the entry is copied from the * UDATA entry field to the symbol table. * - * Return: Success: Non-negative if found and data returned through - * the UDATA pointer. + * Return: Success: Non-negative (TRUE/FALSE) if found and data + * returned through the UDATA pointer. * * Failure: Negative if not found. * @@ -914,7 +493,7 @@ H5G_node_cmp3(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata, * *------------------------------------------------------------------------- */ -static herr_t +static htri_t H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key, void *_udata) { @@ -923,8 +502,8 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key unsigned lt = 0, idx = 0, rt; int cmp = 1; const char *s; - const char *base; /* Base of heap */ - herr_t ret_value = SUCCEED; /* Return value */ + const char *base; /* Base of heap */ + htri_t ret_value = TRUE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5G_node_found) @@ -961,7 +540,7 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key } /* end while */ if(cmp) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found") + HGOTO_DONE(FALSE) /* Call user's callback operator */ if((udata->op)(&sn->entry[idx], udata->op_data) < 0) @@ -1292,14 +871,8 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, *rt_key = *lt_key; *rt_key_changed = TRUE; sn->nsyms = 0; - if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5G_node_size_real(f)) < 0 - || H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0) { - sn = NULL; - HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to free symbol table node") - } /* end if */ - sn = NULL; + sn_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; ret_value = H5B_INS_REMOVE; - } else if(0 == idx) { /* * We are about to remove the left-most entry from the symbol table @@ -1311,7 +884,6 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, HDmemmove(sn->entry + idx, sn->entry + idx + 1, (sn->nsyms-idx) * sizeof(H5G_entry_t)); ret_value = H5B_INS_NOOP; - } else if (idx + 1 == sn->nsyms) { /* * We are about to remove the right-most entry from the symbol table @@ -1323,7 +895,6 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, rt_key->offset = sn->entry[sn->nsyms - 1].name_off; *rt_key_changed = TRUE; ret_value = H5B_INS_NOOP; - } else { /* * We are about to remove an entry from the middle of a symbol table @@ -1364,12 +935,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, *rt_key = *lt_key; *rt_key_changed = TRUE; sn->nsyms = 0; - if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5G_node_size_real(f)) < 0 - || H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0) { - sn = NULL; - HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to free symbol table node") - } /* end if */ - sn = NULL; + sn_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; ret_value = H5B_INS_REMOVE; } /* end else */ diff --git a/src/H5Gobj.c b/src/H5Gobj.c index a9d6e1a..e0d5434 100644 --- a/src/H5Gobj.c +++ b/src/H5Gobj.c @@ -141,6 +141,10 @@ H5G_obj_create(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo, HDassert(ginfo); HDassert(oloc); + /* Check for invalid access request */ + if(0 == (f->intent & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "no write intent on file") + /* Check for using the latest version of the group format */ /* (add more checks for creating "new format" groups when needed) */ if(H5F_USE_LATEST_FORMAT(f) || linfo->track_corder) @@ -322,36 +326,41 @@ H5G_obj_ent_encode(const H5F_t *f, uint8_t **pp, const H5O_loc_t *oloc) * *------------------------------------------------------------------------- */ -H5O_linfo_t * +htri_t H5G_obj_get_linfo(const H5O_loc_t *grp_oloc, H5O_linfo_t *linfo, hid_t dxpl_id) { - H5O_linfo_t *ret_value; /* Return value */ + htri_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5G_obj_get_linfo, NULL) + FUNC_ENTER_NOAPI(H5G_obj_get_linfo, FAIL) /* check arguments */ HDassert(grp_oloc); + HDassert(linfo); + + /* Check for the group having a link info message */ + if((ret_value = H5O_msg_exists(grp_oloc, H5O_LINFO_ID, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read object header") + if(ret_value) { + /* Retrieve the "link info" structure */ + if(NULL == H5O_msg_read(grp_oloc, H5O_LINFO_ID, linfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "link info message not present") - /* Retrieve the "link info" structure */ - if((ret_value = (H5O_linfo_t *)H5O_msg_read(grp_oloc, H5O_LINFO_ID, linfo, dxpl_id))) { /* Check if we don't know how many links there are */ - if(ret_value->nlinks == HSIZET_MAX) { + if(linfo->nlinks == HSIZET_MAX) { /* Check if we are using "dense" link storage */ - if(H5F_addr_defined(ret_value->fheap_addr)) { + if(H5F_addr_defined(linfo->fheap_addr)) { /* Retrieve # of records in "name" B-tree */ /* (should be same # of records in all indices) */ - if(H5B2_get_nrec(grp_oloc->file, dxpl_id, H5G_BT2_NAME, ret_value->name_bt2_addr, &ret_value->nlinks) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't retrieve # of records in index") + if(H5B2_get_nrec(grp_oloc->file, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &linfo->nlinks) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve # of records in index") } /* end if */ else { /* Retrieve # of links from object header */ - if(H5O_get_nlinks(grp_oloc, dxpl_id, &ret_value->nlinks) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't retrieve # of links for object") + if(H5O_get_nlinks(grp_oloc, dxpl_id, &linfo->nlinks) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve # of links for object") } /* end if */ } /* end if */ } /* end if */ - else - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "link info message not present") done: FUNC_LEAVE_NOAPI(ret_value) @@ -452,6 +461,7 @@ 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) { H5O_linfo_t linfo; /* Link info message */ + htri_t linfo_exists; /* Whether the link info message exists */ hbool_t use_old_format; /* Whether to use 'old format' (symbol table) for insertions or not */ hbool_t use_new_dense = FALSE; /* Whether to use "dense" form of 'new format' group */ herr_t ret_value = SUCCEED; /* Return value */ @@ -465,7 +475,9 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, /* Check if we have information about the number of objects in this group */ /* (by attempting to get the link info message for this group) */ - if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) { + if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message") + if(linfo_exists) { H5O_ginfo_t ginfo; /* Group info message */ size_t link_msg_size; /* Size of new link message in the file */ @@ -525,9 +537,6 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, } /* end else */ } /* end if */ else { - /* Clear error stack from not finding the link info message */ - H5E_clear_stack(NULL); - /* Check for new-style link information */ if(obj_lnk->cset != H5T_CSET_ASCII || obj_lnk->type > H5L_TYPE_BUILTIN_MAX) { H5O_linfo_t new_linfo = H5G_CRT_LINK_INFO_DEF; /* Link information */ @@ -636,6 +645,7 @@ H5G_obj_iterate(const H5O_loc_t *grp_oloc, H5G_lib_iterate_t op, void *op_data, hid_t dxpl_id) { H5O_linfo_t linfo; /* Link info message */ + htri_t linfo_exists; /* Whether the link info message exists */ herr_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_obj_iterate, FAIL) @@ -645,7 +655,9 @@ H5G_obj_iterate(const H5O_loc_t *grp_oloc, HDassert(op); /* Attempt to get the link info for this group */ - if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) { + if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message") + if(linfo_exists) { /* 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") @@ -669,9 +681,6 @@ H5G_obj_iterate(const H5O_loc_t *grp_oloc, } /* end else */ } /* 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) HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query") @@ -707,6 +716,7 @@ H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id) H5G_name_t grp_path; /* Group hier. path */ H5O_loc_t grp_oloc; /* Group object location */ H5O_linfo_t linfo; /* Link info message */ + htri_t linfo_exists; /* Whether the link info message exists */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_obj_info, FAIL) @@ -732,7 +742,9 @@ H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id) grp_info->mounted = H5G_MOUNTED(grp); /* Attempt to get the link info for this group */ - if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) { + if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message") + if(linfo_exists) { /* Retrieve the information about the links */ grp_info->nlinks = linfo.nlinks; grp_info->max_corder = linfo.max_corder; @@ -744,9 +756,6 @@ H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id) grp_info->storage_type = H5G_STORAGE_TYPE_COMPACT; } /* end if */ else { - /* Clear error stack from not finding the link info message */ - H5E_clear_stack(NULL); - /* Get the number of objects in this group by iterating over symbol table */ if(H5G_stab_count(oloc, &grp_info->nlinks, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "can't count objects") @@ -783,6 +792,7 @@ 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) { H5O_linfo_t linfo; /* Link info message */ + htri_t linfo_exists; /* Whether the link info message exists */ ssize_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_obj_get_name_by_idx, FAIL) @@ -791,7 +801,9 @@ H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type, HDassert(oloc && oloc->file); /* Attempt to get the link info for this group */ - if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) { + if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message") + if(linfo_exists) { /* Check for creation order tracking, if creation order index lookup requested */ if(idx_type == H5_INDEX_CRT_ORDER) { /* Check if creation order is tracked */ @@ -812,9 +824,6 @@ H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type, } /* end else */ } /* 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) HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query") @@ -955,6 +964,7 @@ herr_t H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, hid_t dxpl_id) { H5O_linfo_t linfo; /* Link info message */ + htri_t linfo_exists; /* Whether the link info message exists */ hbool_t use_old_format; /* Whether to use 'old format' (symbol table) for deletion or not */ herr_t ret_value = SUCCEED; /* Return value */ @@ -965,7 +975,9 @@ H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, h HDassert(name && *name); /* Attempt to get the link info for this group */ - if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) { + if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message") + if(linfo_exists) { /* Using the new format for groups */ use_old_format = FALSE; @@ -982,9 +994,6 @@ H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, h } /* end else */ } /* end if */ else { - /* Clear error stack from not finding the link info message */ - H5E_clear_stack(NULL); - /* Using the old format for groups */ use_old_format = TRUE; @@ -1021,6 +1030,7 @@ H5G_obj_remove_by_idx(H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t dxpl_id) { H5O_linfo_t linfo; /* Link info message */ + htri_t linfo_exists; /* Whether the link info message exists */ hbool_t use_old_format; /* Whether to use 'old format' (symbol table) for deletion or not */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1030,7 +1040,9 @@ H5G_obj_remove_by_idx(H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r, HDassert(grp_oloc && grp_oloc->file); /* Attempt to get the link info for this group */ - if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) { + if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message") + if(linfo_exists) { /* Check for creation order tracking, if creation order index lookup requested */ if(idx_type == H5_INDEX_CRT_ORDER) { /* Check if creation order is tracked */ @@ -1093,12 +1105,13 @@ done: * *------------------------------------------------------------------------- */ -herr_t +htri_t H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, hid_t dxpl_id) { H5O_linfo_t linfo; /* Link info message */ - herr_t ret_value = SUCCEED; /* Return value */ + htri_t linfo_exists; /* Whether the link info message exists */ + htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI(H5G_obj_lookup, FAIL) @@ -1107,25 +1120,24 @@ H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, HDassert(name && *name); /* Attempt to get the link info message for this group */ - if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) { + if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message") + if(linfo_exists) { /* Check for dense link storage */ if(H5F_addr_defined(linfo.fheap_addr)) { /* Get the object's info from the dense link storage */ - if(H5G_dense_lookup(grp_oloc->file, dxpl_id, &linfo, name, lnk) < 0) + if((ret_value = H5G_dense_lookup(grp_oloc->file, dxpl_id, &linfo, name, lnk)) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") } /* end if */ else { /* Get the object's info from the link messages */ - if(H5G_compact_lookup(grp_oloc, name, lnk, dxpl_id) < 0) + if((ret_value = H5G_compact_lookup(grp_oloc, name, lnk, dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") } /* end else */ } /* end if */ else { - /* Clear error stack from not finding the link info message */ - H5E_clear_stack(NULL); - /* Get the object's info from the symbol table */ - if(H5G_stab_lookup(grp_oloc, name, lnk, dxpl_id) < 0) + if((ret_value = H5G_stab_lookup(grp_oloc, name, lnk, dxpl_id)) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") } /* end else */ @@ -1153,6 +1165,7 @@ H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, H5O_link_t *lnk, hid_t dxpl_id) { H5O_linfo_t linfo; /* Link info message */ + htri_t linfo_exists; /* Whether the link info message exists */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_obj_lookup_by_idx, FAIL) @@ -1161,7 +1174,9 @@ H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type, HDassert(grp_oloc && grp_oloc->file); /* Attempt to get the link info message for this group */ - if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) { + if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message") + if(linfo_exists) { /* Check for creation order tracking, if creation order index lookup requested */ if(idx_type == H5_INDEX_CRT_ORDER) { /* Check if creation order is tracked */ @@ -1182,9 +1197,6 @@ H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type, } /* end else */ } /* 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) HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query") diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index b2cef28..31e5713 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -110,6 +110,19 @@ typedef struct H5G_entry_t { } H5G_entry_t; /* + * A symbol table node is a collection of symbol table entries. It can + * be thought of as the lowest level of the B-link tree that points to + * a collection of symbol table entries that belong to a specific symbol + * table or group. + */ +typedef struct H5G_node_t { + H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */ + /* first field in structure */ + unsigned nsyms; /*number of symbols */ + H5G_entry_t *entry; /*array of symbol table entries */ +} H5G_node_t; + +/* * Shared information for all open group objects */ struct H5G_shared_t { @@ -412,6 +425,7 @@ H5_DLL herr_t H5G_ent_debug(H5F_t *f, const H5G_entry_t *ent, /* Functions that understand symbol table nodes */ H5_DLL herr_t H5G_node_init(H5F_t *f); +H5_DLL size_t H5G_node_size_real(const H5F_t *f); H5_DLL int H5G_node_iterate(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr, const void *_rt_key, void *_udata); H5_DLL int H5G_node_sumup(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr, @@ -462,7 +476,7 @@ H5_DLL herr_t H5G_compact_remove_by_idx(const H5O_loc_t *oloc, hid_t dxpl_id, 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, +H5_DLL htri_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, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, @@ -478,7 +492,7 @@ H5_DLL herr_t H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t * H5_DLL herr_t H5G_dense_create(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo); H5_DLL herr_t H5G_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, const H5O_link_t *lnk); -H5_DLL herr_t H5G_dense_lookup(H5F_t *f, hid_t dxpl_id, +H5_DLL htri_t H5G_dense_lookup(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, const char *name, H5O_link_t *lnk); H5_DLL herr_t H5G_dense_lookup_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, @@ -504,8 +518,8 @@ H5_DLL H5G_obj_t H5G_dense_get_type_by_idx(H5F_t *f, hid_t dxpl_id, /* Functions that understand group objects */ H5_DLL herr_t H5G_obj_create(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo, const H5O_linfo_t *linfo, hid_t gcpl_id, H5O_loc_t *oloc/*out*/); -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 htri_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(const H5O_loc_t *grp_oloc, @@ -518,7 +532,7 @@ H5_DLL herr_t H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, hid_t dxpl_id); H5_DLL herr_t H5G_obj_remove_by_idx(H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t dxpl_id); -H5_DLL herr_t H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, +H5_DLL htri_t H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, hid_t dxpl_id); H5_DLL herr_t H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t n, H5O_link_t *lnk, hid_t dxpl_id); diff --git a/src/H5Gstab.c b/src/H5Gstab.c index 8ab9deb..f79d78b 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -810,7 +810,7 @@ done: * * Purpose: Look up an object relative to a group, using symbol table * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative (TRUE/FALSE) on success/Negative on failure * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu @@ -818,7 +818,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +htri_t H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, hid_t dxpl_id) { @@ -826,7 +826,7 @@ H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, H5G_bt_lkp_t bt_udata; /* Data to pass through B-tree */ H5G_stab_fnd_ud_t udata; /* 'User data' to give to callback */ H5O_stab_t stab; /* Symbol table message */ - herr_t ret_value = SUCCEED; /* Return value */ + htri_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5G_stab_lookup, FAIL) @@ -856,7 +856,7 @@ H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, bt_udata.op_data = &udata; /* Search the B-tree */ - if(H5B_find(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &bt_udata) < 0) + if((ret_value = H5B_find(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &bt_udata)) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found") done: diff --git a/src/H5Gtest.c b/src/H5Gtest.c index be9ab14..d7f102f 100644 --- a/src/H5Gtest.c +++ b/src/H5Gtest.c @@ -133,7 +133,7 @@ H5G_is_empty_test(hid_t gid) HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "both symbol table and link info messages found") /* Get the link info */ - if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id)) + if(H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info") /* Check for 'dense' link storage file addresses being defined */ @@ -343,7 +343,7 @@ H5G_is_new_dense_test(hid_t gid) H5O_linfo_t linfo; /* Link info message */ /* Get the link info */ - if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id)) + if(H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info") /* Check for 'dense' link storage file addresses being defined */ @@ -393,7 +393,7 @@ H5G_new_dense_info_test(hid_t gid, hsize_t *name_count, hsize_t *corder_count) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") /* Get the link info */ - if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id)) + if(H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info") /* Check for 'dense' link storage file addresses being defined */ diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c index 7693343..87ebc74 100644 --- a/src/H5Gtraverse.c +++ b/src/H5Gtraverse.c @@ -633,7 +633,7 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, /* Traverse the path */ while((name = H5G_component(name, &nchars)) && *name) { const char *s; /* Temporary string pointer */ - herr_t lookup_status; /* Status from object lookup */ + htri_t lookup_status; /* Status from object lookup */ /* * Copy the component name into a null-terminated buffer so @@ -661,11 +661,11 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, } /* end if */ /* Get information for object in current group */ - /* (Defer issuing error for bad lookup until later) */ - lookup_status = H5G_obj_lookup(grp_loc.oloc, H5G_comp_g, &lnk/*out*/, dxpl_id); + if((lookup_status = H5G_obj_lookup(grp_loc.oloc, H5G_comp_g, &lnk/*out*/, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't look up component") /* If the lookup was OK, build object location and traverse special links, etc. */ - if(lookup_status >= 0) { + if(lookup_status) { /* Sanity check link and indicate it's valid */ HDassert(lnk.type >= H5L_TYPE_HARD); HDassert(!HDstrcmp(H5G_comp_g, lnk.name)); @@ -688,14 +688,14 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, H5G_loc_t *cb_loc; /* Pointer to object location for callback */ /* Set callback parameters appropriately, based on link being found */ - if(lookup_status < 0) { + if(lookup_status) { + cb_lnk = &lnk; + cb_loc = &obj_loc; + } /* end if */ + else { HDassert(!obj_loc_valid); cb_lnk = NULL; cb_loc = NULL; - } /* end if */ - else { - cb_lnk = &lnk; - cb_loc = &obj_loc; } /* end else */ /* Call 'operator' routine */ @@ -706,7 +706,7 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, } /* end if */ /* Handle lookup failures now */ - if(lookup_status < 0) { + if(!lookup_status) { /* If an intermediate group doesn't exist & flag is set, create the group */ if(target & H5G_CRT_INTMD_GROUP) { const H5O_ginfo_t def_ginfo = H5G_CRT_GROUP_INFO_DEF; /* Default group info settings */ @@ -714,31 +714,32 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, H5O_ginfo_t par_ginfo; /* Group info settings for parent group */ H5O_linfo_t par_linfo; /* Link info settings for parent group */ H5O_linfo_t tmp_linfo; /* Temporary link info settings */ + htri_t exists; /* Whether a group or link info message exists */ const H5O_ginfo_t *ginfo; /* Group info settings for new group */ const H5O_linfo_t *linfo; /* Link info settings for new group */ - /* Get the group info for parent group */ + /* Check for the parent group having a group info message */ /* (OK if not found) */ - if(NULL == H5O_msg_read(grp_loc.oloc, H5O_GINFO_ID, &par_ginfo, dxpl_id)) { - /* Clear error stack from not finding the group info message */ - H5E_clear_stack(NULL); - - /* Use default group info settings */ - ginfo = &def_ginfo; + if((exists = H5O_msg_exists(grp_loc.oloc, H5O_GINFO_ID, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read object header") + if(exists) { + /* Get the group info for parent group */ + if(NULL == H5O_msg_read(grp_loc.oloc, H5O_GINFO_ID, &par_ginfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "group info message not present") + + /* Use parent group info settings */ + ginfo = &par_ginfo; } /* end if */ else - ginfo = &par_ginfo; + /* Use default group info settings */ + ginfo = &def_ginfo; - /* Get the link info for parent group */ + /* Check for the parent group having a link info message */ /* (OK if not found) */ - if(NULL == H5G_obj_get_linfo(grp_loc.oloc, &par_linfo, dxpl_id)) { - /* Clear error stack from not finding the link info message */ - H5E_clear_stack(NULL); - - /* Use default link info settings */ - linfo = &def_linfo; - } /* end if */ - else { + /* Get the link info for parent group */ + if((exists = H5G_obj_get_linfo(grp_loc.oloc, &par_linfo, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read object header") + if(exists) { /* Only keep the creation order information from the parent * group's link info */ @@ -746,7 +747,10 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, tmp_linfo.track_corder = par_linfo.track_corder; tmp_linfo.index_corder = par_linfo.index_corder; linfo = &tmp_linfo; - } /* end else */ + } /* end if */ + else + /* Use default link info settings */ + linfo = &def_linfo; /* Create the intermediate group */ /* XXX: Should we allow user to control the group creation params here? -QAK */ diff --git a/src/H5HFcache.c b/src/H5HFcache.c index f057c7c..8b29bc7 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -30,6 +30,7 @@ #define H5HF_PACKAGE /*suppress error about including H5HFpkg */ + /***********/ /* Headers */ /***********/ @@ -41,6 +42,7 @@ #include "H5Vprivate.h" /* Vectors and arrays */ #include "H5WBprivate.h" /* Wrapped Buffers */ + /****************/ /* Local Macros */ /****************/ @@ -89,6 +91,7 @@ static herr_t H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, static herr_t H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy); static herr_t H5HF_cache_dblock_size(const H5F_t *f, const H5HF_direct_t *dblock, size_t *size_ptr); + /*********************/ /* Package Variables */ /*********************/ @@ -593,11 +596,12 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ herr_t -H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr) +H5HF_cache_hdr_dest(H5F_t *f, H5HF_hdr_t *hdr) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_dest) + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_hdr_dest) /* * Check arguments. @@ -605,6 +609,17 @@ H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr) HDassert(hdr); HDassert(hdr->rc == 0); + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!hdr->cache_info.free_file_space_on_destroy || H5F_addr_defined(hdr->cache_info.addr)); + + /* Check for freeing file space for heap header */ + if(hdr->cache_info.free_file_space_on_destroy) { + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_FHEAP_HDR, H5AC_dxpl_id, hdr->cache_info.addr, (hsize_t)hdr->heap_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap header") + } /* end if */ + /* Free the block size lookup table for the doubling table */ H5HF_dtable_dest(&hdr->man_dtable); @@ -615,7 +630,8 @@ H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr) /* Free the shared info itself */ (void)H5FL_FREE(H5HF_hdr_t, hdr); - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_cache_hdr_dest() */ @@ -1071,7 +1087,6 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ herr_t H5HF_cache_iblock_dest(H5F_t *f, H5HF_indirect_t *iblock) { @@ -1089,6 +1104,17 @@ H5HF_cache_iblock_dest(H5F_t *f, H5HF_indirect_t *iblock) HDfprintf(stderr, "%s: Destroying indirect block\n", FUNC); #endif /* QAK */ + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!iblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(iblock->cache_info.addr)); + + /* Check for freeing file space for indirect block */ + if(iblock->cache_info.free_file_space_on_destroy) { + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_FHEAP_IBLOCK, H5AC_dxpl_id, iblock->cache_info.addr, (hsize_t)iblock->size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block") + } /* end if */ + /* Set the shared heap header's file context for this operation */ iblock->hdr->f = f; @@ -1234,6 +1260,7 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, /* Set block's internal information */ dblock->size = *size; + dblock->file_size = 0; dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size); /* Allocate block buffer */ @@ -1622,7 +1649,6 @@ done: * *------------------------------------------------------------------------- */ -/* ARGSUSED */ herr_t H5HF_cache_dblock_dest(H5F_t *f, H5HF_direct_t *dblock) { @@ -1638,6 +1664,20 @@ H5HF_cache_dblock_dest(H5F_t *f, H5HF_direct_t *dblock) HDfprintf(stderr, "%s: Destroying direct block, dblock = %p\n", FUNC, dblock); #endif /* QAK */ + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!dblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblock->cache_info.addr)); + + /* Check for freeing file space for direct block */ + if(dblock->cache_info.free_file_space_on_destroy) { + /* Sanity check */ + HDassert(dblock->file_size > 0); + + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, H5AC_dxpl_id, dblock->cache_info.addr, dblock->file_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block") + } /* end if */ + /* Set the shared heap header's file context for this operation */ dblock->hdr->f = f; diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c index 9bc5b20..a4ce8b2 100644 --- a/src/H5HFdblock.c +++ b/src/H5HFdblock.c @@ -137,6 +137,7 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo dblock->block_off = 0; dblock->size = hdr->man_dtable.cparam.start_block_size; } /* end else */ + dblock->file_size = 0; dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size); free_space = dblock->size - H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); @@ -220,6 +221,7 @@ H5HF_man_dblock_destroy(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_direct_t *dblock, haddr_t dblock_addr) { hsize_t dblock_size; /* Size of direct block on disk */ + unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting indirect block */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_destroy) @@ -325,16 +327,15 @@ HDfprintf(stderr, "%s: Reversing iterator\n", FUNC); HDfprintf(stderr, "%s: Before releasing direct block's space, dblock_addr = %a, dblock_size = %Hu\n", FUNC, dblock_addr, dblock_size); #endif /* QAK */ - /* Release direct block's disk space */ - if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, dblock_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block") - - /* Remove direct block from metadata cache */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") - dblock = NULL; + /* Indicate that the indirect block should be deleted & file space freed */ + dblock->file_size = dblock_size; + cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; done: + /* Unprotect the indirect block, with appropriate flags */ + if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, cache_flags) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_dblock_destroy() */ @@ -688,7 +689,7 @@ HDfprintf(stderr, "%s: dblock_addr = %a, dblock_size = %Hu\n", FUNC, dblock_addr HDfprintf(stderr, "%s: Expunging direct block from cache\n", FUNC); #endif /* QAK */ /* Evict the direct block from the metadata cache */ - if(H5AC_expunge_entry(f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr) < 0) + if(H5AC_expunge_entry(f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove direct block from cache") #ifdef QAK HDfprintf(stderr, "%s: Done expunging direct block from cache\n", FUNC); @@ -696,6 +697,19 @@ HDfprintf(stderr, "%s: Done expunging direct block from cache\n", FUNC); } /* end if */ /* Release direct block's disk space */ + /* (XXX: Under the best of circumstances, this block's space in the file + * would be freed in the H5AC_expunge_entry() call above (and the + * H5AC__FREE_FILE_SPACE_FLAG used there), but since the direct + * block structure might have a different size on disk than in + * the heap's 'abstract' address space, we would need to set the + * "file_size" field for the direct block structure. In order to + * do that, we'd have to protect/unprotect the direct block and + * that would add a bunch of unnecessary overhead to the process, + * so we just release the file space here, directly. When the + * revised metadata cache is operating, it will "know" the file + * size of each entry in the cache and we can the the + * H5AC_expunge_entry() method. -QAK) + */ if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, dblock_size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block") diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c index ffd90e8..4fd527d 100644 --- a/src/H5HFhdr.c +++ b/src/H5HFhdr.c @@ -1505,6 +1505,7 @@ done: herr_t H5HF_hdr_delete(H5HF_hdr_t *hdr, hid_t dxpl_id) { + unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap header */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5HF_hdr_delete, FAIL) @@ -1585,18 +1586,12 @@ HDfprintf(stderr, "%s: hdr->huge_bt2_addr = %a\n", FUNC, hdr->huge_bt2_addr); HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap 'huge' objects and tracker") } /* end if */ - /* Release header's disk space */ - if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_HDR, dxpl_id, hdr->heap_addr, (hsize_t)hdr->heap_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap header") - - /* Finished deleting header */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, hdr, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap header") - hdr = NULL; + /* Indicate that the heap header should be deleted & file space freed */ + cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; done: - /* Unprotect the header, if an error occurred */ - if(hdr && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, hdr, H5AC__NO_FLAGS_SET) < 0) + /* Unprotect the header with appropriate flags */ + if(hdr && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, hdr, cache_flags) < 0) HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap header") FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5HFhuge.c b/src/H5HFhuge.c index 198ef62..db9f7a1 100644 --- a/src/H5HFhuge.c +++ b/src/H5HFhuge.c @@ -545,7 +545,7 @@ H5HF_huge_get_obj_len(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, /* Look up object in v2 B-tree */ if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_FILT_INDIR, hdr->huge_bt2_addr, - &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) < 0) + &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) != TRUE) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree") /* Retrieve the object's length */ @@ -560,7 +560,7 @@ H5HF_huge_get_obj_len(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, /* Look up object in v2 B-tree */ if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr, - &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0) + &search_rec, H5HF_huge_bt2_indir_found, &found_rec) != TRUE) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree") /* Retrieve the object's length */ @@ -628,7 +628,7 @@ H5HF_huge_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, /* Look up object in v2 B-tree */ if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_FILT_INDIR, hdr->huge_bt2_addr, - &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) < 0) + &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) != TRUE) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree") /* Retrieve the object's address & length */ @@ -645,7 +645,7 @@ H5HF_huge_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, /* Look up object in v2 B-tree */ if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr, - &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0) + &search_rec, H5HF_huge_bt2_indir_found, &found_rec) != TRUE) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree") /* Retrieve the object's address & length */ @@ -764,7 +764,7 @@ H5HF_huge_write(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, /* Look up object in v2 B-tree */ if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr, - &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0) + &search_rec, H5HF_huge_bt2_indir_found, &found_rec) != TRUE) HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree") /* Retrieve the object's address & length */ diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c index b5c421a..a01a5be 100644 --- a/src/H5HFiblock.c +++ b/src/H5HFiblock.c @@ -310,12 +310,8 @@ HDfprintf(stderr, "%s: Removing indirect block from cache, iblock->addr = %a\n", iblock->par_entry = 0; } /* end if */ - /* Release space for indirect block on disk */ - if(H5MF_xfree(iblock->hdr->f, H5FD_MEM_FHEAP_IBLOCK, H5AC_dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block disk space") - /* Evict the indirect block from the metadata cache */ - if(H5AC_expunge_entry(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr) < 0) + if(H5AC_expunge_entry(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, H5AC__FREE_FILE_SPACE_FLAG) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove indirect block from cache") } /* end if */ } /* end if */ @@ -1489,6 +1485,7 @@ H5HF_man_iblock_delete(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr, H5HF_indirect_t *iblock; /* Pointer to indirect block */ unsigned row, col; /* Current row & column in indirect block */ unsigned entry; /* Current entry in row */ + unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting indirect block */ hbool_t did_protect; /* Whether we protected the indirect block or not */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1550,10 +1547,6 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr } /* end for */ } /* end row */ - /* Release indirect block's disk space */ - if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock_addr, (hsize_t)iblock->size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block") - #ifndef NDEBUG { unsigned iblock_status = 0; /* Indirect block's status in the metadata cache */ @@ -1567,12 +1560,14 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr } #endif /* NDEBUG */ - /* Finished deleting indirect block in metadata cache */ - if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG, did_protect) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - iblock = NULL; + /* Indicate that the indirect block should be deleted & file space freed */ + cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; done: + /* Unprotect the indirect block, with appropriate flags */ + if(iblock && H5HF_man_iblock_unprotect(iblock, dxpl_id, cache_flags, did_protect) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_iblock_delete() */ diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index 71691c9..bf80164 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -403,6 +403,7 @@ typedef struct H5HF_direct_t { H5HF_indirect_t *parent; /* Shared parent indirect block info */ unsigned par_entry; /* Entry in parent's table */ size_t size; /* Size of direct block */ + hsize_t file_size; /* Size of direct block in file (only valid when block's space is being freed) */ unsigned blk_off_size; /* Size of offsets in the block */ uint8_t *blk; /* Pointer to buffer containing block data */ diff --git a/src/H5HFsection.c b/src/H5HFsection.c index 091ec79..81b353f 100644 --- a/src/H5HFsection.c +++ b/src/H5HFsection.c @@ -206,6 +206,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{ H5HF_sect_single_shrink, /* Shrink container w/section */ H5HF_sect_single_free, /* Free section */ H5HF_sect_single_valid, /* Check validity of section */ + NULL, /* Split section node for alignment */ NULL, /* Dump debugging for section */ }}; @@ -234,6 +235,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1] = {{ H5HF_sect_row_shrink, /* Shrink container w/section */ H5HF_sect_row_free, /* Free section */ H5HF_sect_row_valid, /* Check validity of section */ + NULL, /* Split section node for alignment */ H5HF_sect_row_debug, /* Dump debugging for section */ }}; @@ -259,6 +261,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1] = {{ NULL, /* Shrink container w/section */ H5HF_sect_row_free, /* Free section */ H5HF_sect_row_valid, /* Check validity of section */ + NULL, /* Split section node for alignment */ H5HF_sect_row_debug, /* Dump debugging for section */ }}; @@ -287,6 +290,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{ NULL, /* Shrink container w/section */ NULL, /* Free section */ NULL, /* Check validity of section */ + NULL, /* Split section node for alignment */ NULL, /* Dump debugging for section */ }}; diff --git a/src/H5HFspace.c b/src/H5HFspace.c index 77d8b1b..7978a96 100644 --- a/src/H5HFspace.c +++ b/src/H5HFspace.c @@ -44,6 +44,8 @@ #define H5HF_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */ #define H5HF_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */ +#define H5HF_FSPACE_THRHD_DEF 1 /* Default: no alignment threshold */ +#define H5HF_FSPACE_ALIGN_DEF 1 /* Default: no alignment */ /******************/ /* Local Typedefs */ @@ -91,6 +93,11 @@ * koziol@ncsa.uiuc.edu * May 2 2006 * + * Modifications: + * Vailin Choi, July 29th, 2008 + * Pass values of alignment and threshold to FS_create() and FS_open() + * for handling alignment. + * *------------------------------------------------------------------------- */ herr_t @@ -114,7 +121,7 @@ H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t may_create) if(H5F_addr_defined(hdr->fs_addr)) { /* Open an existing free space structure for the heap */ if(NULL == (hdr->fspace = H5FS_open(hdr->f, dxpl_id, hdr->fs_addr, - NELMTS(classes), classes, hdr))) + NELMTS(classes), classes, hdr, H5HF_FSPACE_THRHD_DEF, H5HF_FSPACE_ALIGN_DEF))) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info") } /* end if */ else { @@ -131,8 +138,9 @@ H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t may_create) /* 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))) + &fs_create, NELMTS(classes), classes, hdr, H5HF_FSPACE_THRHD_DEF, H5HF_FSPACE_ALIGN_DEF))) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info") + HDassert(H5F_addr_defined(hdr->fs_addr)); } /* end if */ } /* end else */ @@ -351,7 +359,7 @@ H5HF_space_close(H5HF_hdr_t *hdr, hid_t dxpl_id) hsize_t nsects; /* Number of sections for this heap */ /* Retrieve the number of sections for this heap */ - if(H5FS_get_sect_count(hdr->fspace, &nsects) < 0) + if(H5FS_sect_stats(hdr->fspace, NULL, &nsects) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTCOUNT, FAIL, "can't query free space section count") #ifdef QAK HDfprintf(stderr, "%s: nsects = %Hu\n", FUNC, nsects); @@ -37,33 +37,28 @@ * in the collection, and temporal locality. */ +/****************/ +/* Module Setup */ +/****************/ + #define H5F_PACKAGE /*suppress error about including H5Fpkg */ #define H5HG_PACKAGE /*suppress error about including H5HGpkg */ +/***********/ +/* Headers */ +/***********/ #include "H5private.h" /* Generic Functions */ -#include "H5ACprivate.h" /* Metadata cache */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ -#include "H5FLprivate.h" /* Free lists */ #include "H5HGpkg.h" /* Global heaps */ #include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ -/* Private macros */ -/* - * Global heap collection version. - */ -#define H5HG_VERSION 1 - -/* - * All global heap collections are at least this big. This allows us to read - * most collections with a single read() since we don't have to read a few - * bytes of header to figure out the size. If the heap is larger than this - * then a second read gets the rest after we've decoded the header. - */ -#define H5HG_MINSIZE 4096 +/****************/ +/* Local Macros */ +/****************/ /* * Limit global heap collections to the some reasonable size. This is @@ -73,12 +68,6 @@ #define H5HG_MAXSIZE 65536 /* - * Maximum length of the CWFS list, the list of remembered collections that - * have free space. - */ -#define H5HG_NCWFS 16 - -/* * The maximum number of links allowed to a global heap object. */ #define H5HG_MAXLINK 65535 @@ -88,63 +77,47 @@ */ #define H5HG_MAXIDX 65535 -/* - * The size of the collection header, always a multiple of the alignment so - * that the stuff that follows the header is aligned. - */ -#define H5HG_SIZEOF_HDR(f) \ - H5HG_ALIGN(4 + /*magic number */ \ - 1 + /*version number */ \ - 3 + /*reserved */ \ - H5F_SIZEOF_SIZE(f)) /*collection size */ -/* - * The initial guess for the number of messages in a collection. We assume - * that all objects in that collection are zero length, giving the maximum - * possible number of objects in the collection. The collection itself has - * some overhead and each message has some overhead. The `+2' accounts for - * rounding and for the free space object. - */ -#define H5HG_NOBJS(f,z) (int)((((z)-H5HG_SIZEOF_HDR(f))/ \ - H5HG_SIZEOF_OBJHDR(f)+2)) +/******************/ +/* Local Typedefs */ +/******************/ + -/* Private typedefs */ +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ -/* PRIVATE PROTOTYPES */ static haddr_t H5HG_create(H5F_t *f, hid_t dxpl_id, size_t size); -#ifdef NOT_YET -static void *H5HG_peek(H5F_t *f, hid_t dxpl_id, H5HG_t *hobj); -#endif /* NOT_YET */ - -/* Metadata cache callbacks */ -static H5HG_heap_t *H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, - void *udata2); -static herr_t H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, - H5HG_heap_t *heap, unsigned UNUSED * flags_ptr); -static herr_t H5HG_dest(H5F_t *f, H5HG_heap_t *heap); -static herr_t H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy); -static herr_t H5HG_compute_size(const H5F_t *f, const H5HG_heap_t *heap, size_t *size_ptr); -/* - * H5HG inherits cache-like properties from H5AC - */ -const H5AC_class_t H5AC_GHEAP[1] = {{ - H5AC_GHEAP_ID, - (H5AC_load_func_t)H5HG_load, - (H5AC_flush_func_t)H5HG_flush, - (H5AC_dest_func_t)H5HG_dest, - (H5AC_clear_func_t)H5HG_clear, - (H5AC_size_func_t)H5HG_compute_size, -}}; + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ /* Declare a free list to manage the H5HG_t struct */ -H5FL_DEFINE_STATIC(H5HG_heap_t); +H5FL_DEFINE(H5HG_heap_t); /* Declare a free list to manage sequences of H5HG_obj_t's */ -H5FL_SEQ_DEFINE_STATIC(H5HG_obj_t); +H5FL_SEQ_DEFINE(H5HG_obj_t); /* Declare a PQ free list to manage heap chunks */ -H5FL_BLK_DEFINE_STATIC(heap_chunk); +H5FL_BLK_DEFINE(gheap_chunk); + /*------------------------------------------------------------------------- @@ -213,7 +186,7 @@ H5HG_create (H5F_t *f, hid_t dxpl_id, size_t size) heap->addr = addr; heap->size = size; - if (NULL==(heap->chunk = H5FL_BLK_MALLOC (heap_chunk,size))) + if (NULL==(heap->chunk = H5FL_BLK_MALLOC (gheap_chunk,size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, \ "memory allocation failed"); #ifdef H5_CLEAR_MEMORY @@ -294,361 +267,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5HG_load - * - * Purpose: Loads a global heap collection from disk. - * - * Return: Success: Ptr to a global heap collection. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Friday, March 27, 1998 - * - * Modifications: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - *------------------------------------------------------------------------- - */ -static H5HG_heap_t * -H5HG_load (H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, - void UNUSED * udata2) -{ - H5HG_heap_t *heap = NULL; - uint8_t *p = NULL; - int i; - size_t nalloc, need; - size_t max_idx=0; /* The maximum index seen */ - H5HG_heap_t *ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI(H5HG_load, NULL); - - /* check arguments */ - assert (f); - assert (H5F_addr_defined (addr)); - assert (!udata1); - assert (!udata2); - - /* Read the initial 4k page */ - if(NULL == (heap = H5FL_CALLOC (H5HG_heap_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - heap->addr = addr; - if(NULL == (heap->chunk = H5FL_BLK_MALLOC(heap_chunk, (size_t)H5HG_MINSIZE))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if(H5F_block_read(f, H5FD_MEM_GHEAP, addr, (size_t)H5HG_MINSIZE, dxpl_id, heap->chunk)<0) - HGOTO_ERROR (H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection"); - - /* Magic number */ - if(HDmemcmp(heap->chunk, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC)) - HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "bad global heap collection signature"); - p = heap->chunk + H5_SIZEOF_MAGIC; - - /* Version */ - if (H5HG_VERSION!=*p++) - HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap"); - - /* Reserved */ - p += 3; - - /* Size */ - H5F_DECODE_LENGTH (f, p, heap->size); - assert (heap->size>=H5HG_MINSIZE); - - /* - * If we didn't read enough in the first try, then read the rest of the - * collection now. - */ - if (heap->size > H5HG_MINSIZE) { - haddr_t next_addr = addr + (hsize_t)H5HG_MINSIZE; - if (NULL==(heap->chunk = H5FL_BLK_REALLOC (heap_chunk, heap->chunk, heap->size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if (H5F_block_read (f, H5FD_MEM_GHEAP, next_addr, (heap->size-H5HG_MINSIZE), dxpl_id, heap->chunk+H5HG_MINSIZE)<0) - HGOTO_ERROR (H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection"); - } - - /* Decode each object */ - p = heap->chunk + H5HG_SIZEOF_HDR (f); - nalloc = H5HG_NOBJS (f, heap->size); - if (NULL==(heap->obj = H5FL_SEQ_MALLOC (H5HG_obj_t,nalloc))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - heap->obj[0].size=heap->obj[0].nrefs=0; - heap->obj[0].begin=NULL; - - heap->nalloc = nalloc; - while (p<heap->chunk+heap->size) { - if (p+H5HG_SIZEOF_OBJHDR(f)>heap->chunk+heap->size) { - /* - * The last bit of space is too tiny for an object header, so we - * assume that it's free space. - */ - assert (NULL==heap->obj[0].begin); - heap->obj[0].size = (heap->chunk+heap->size) - p; - heap->obj[0].begin = p; - p += heap->obj[0].size; - } else { - unsigned idx; - uint8_t *begin = p; - - UINT16DECODE (p, idx); - - /* Check if we need more room to store heap objects */ - if(idx>=heap->nalloc) { - size_t new_alloc; /* New allocation number */ - H5HG_obj_t *new_obj; /* New array of object descriptions */ - - /* Determine the new number of objects to index */ - new_alloc=MAX(heap->nalloc*2,(idx+1)); - - /* Reallocate array of objects */ - if (NULL==(new_obj = H5FL_SEQ_REALLOC (H5HG_obj_t, heap->obj, new_alloc))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - - /* Update heap information */ - heap->nalloc=new_alloc; - heap->obj=new_obj; - } /* end if */ - - UINT16DECODE (p, heap->obj[idx].nrefs); - p += 4; /*reserved*/ - H5F_DECODE_LENGTH (f, p, heap->obj[idx].size); - heap->obj[idx].begin = begin; - /* - * The total storage size includes the size of the object header - * and is zero padded so the next object header is properly - * aligned. The last bit of space is the free space object whose - * size is never padded and already includes the object header. - */ - if (idx>0) { - need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(heap->obj[idx].size); - - /* Check for "gap" in index numbers (caused by deletions) and fill in heap object values */ - if(idx>(max_idx+1)) - HDmemset(&heap->obj[max_idx+1],0,sizeof(H5HG_obj_t)*(idx-(max_idx+1))); - max_idx=idx; - } else { - need = heap->obj[idx].size; - } - p = begin + need; - } - } - assert(p==heap->chunk+heap->size); - assert(H5HG_ISALIGNED(heap->obj[0].size)); - - /* Set the next index value to use */ - if(max_idx>0) - heap->nused=max_idx+1; - else - heap->nused=1; - - /* - * Add the new heap to the CWFS list, removing some other entry if - * necessary to make room. We remove the right-most entry that has less - * free space than this heap. - */ - if (!f->shared->cwfs) { - f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5HG_NCWFS * sizeof(H5HG_heap_t *)); - if(NULL == f->shared->cwfs) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - f->shared->ncwfs = 1; - f->shared->cwfs[0] = heap; - } else if(H5HG_NCWFS == f->shared->ncwfs) { - for(i = H5HG_NCWFS - 1; i >= 0; --i) { - if(f->shared->cwfs[i]->obj[0].size < heap->obj[0].size) { - HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, i * sizeof(H5HG_heap_t *)); - f->shared->cwfs[0] = heap; - break; - } /* end if */ - } /* end for */ - } else { - HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, f->shared->ncwfs * sizeof(H5HG_heap_t *)); - f->shared->ncwfs += 1; - f->shared->cwfs[0] = heap; - } /* end else */ - - ret_value = heap; - -done: - if (!ret_value && heap) { - if(H5HG_dest(f,heap)<0) - HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy global heap collection"); - } - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5HG_flush - * - * Purpose: Flushes a global heap collection from memory to disk if it's - * dirty. Optionally deletes teh heap from memory. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Friday, March 27, 1998 - * - * Modifications: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - * - * JRM -- 8/21/06 - * Added the flags_ptr parameter. This parameter exists to - * allow the flush routine to report to the cache if the - * entry is resized or renamed as a result of the flush. - * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HG_flush (H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HG_heap_t *heap, unsigned UNUSED * flags_ptr) -{ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5HG_flush, FAIL); - - /* Check arguments */ - assert (f); - assert (H5F_addr_defined (addr)); - assert (H5F_addr_eq (addr, heap->addr)); - assert (heap); - - if (heap->cache_info.is_dirty) { - if (H5F_block_write (f, H5FD_MEM_GHEAP, addr, heap->size, dxpl_id, heap->chunk)<0) - HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write global heap collection to file"); - heap->cache_info.is_dirty = FALSE; - } - - if (destroy) { - if(H5HG_dest(f,heap)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection"); - } - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5HG_dest - * - * Purpose: Destroys a global heap collection in memory - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Wednesday, January 15, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HG_dest (H5F_t *f, H5HG_heap_t *heap) -{ - int i; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_dest) - - /* Check arguments */ - HDassert(heap); - - /* Verify that node is clean */ - HDassert(heap->cache_info.is_dirty == FALSE); - - for(i = 0; i < f->shared->ncwfs; i++) { - if(f->shared->cwfs[i] == heap) { - f->shared->ncwfs -= 1; - HDmemmove(f->shared->cwfs + i, f->shared->cwfs + i + 1, (f->shared->ncwfs - i) * sizeof(H5HG_heap_t *)); - break; - } /* end if */ - } /* end for */ - - if(heap->chunk) - heap->chunk = H5FL_BLK_FREE(heap_chunk, heap->chunk); - if(heap->obj) - heap->obj = (H5HG_obj_t *)H5FL_SEQ_FREE(H5HG_obj_t, heap->obj); - (void)H5FL_FREE(H5HG_heap_t, heap); - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HG_dest() */ - - -/*------------------------------------------------------------------------- - * Function: H5HG_clear - * - * Purpose: Mark a global heap in memory as non-dirty. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Thursday, March 20, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5HG_clear); - - /* Check arguments */ - assert (heap); - - /* Mark heap as clean */ - heap->cache_info.is_dirty = FALSE; - - if (destroy) - if (H5HG_dest(f, heap) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* H5HG_clear() */ - - -/*------------------------------------------------------------------------- - * Function: H5HG_compute_size - * - * Purpose: Compute the size in bytes of the specified instance of - * H5HG_heap_t on disk, and return it in *len_ptr. On failure, - * the value of *len_ptr is undefined. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: John Mainzer - * 5/13/04 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HG_compute_size(const H5F_t UNUSED *f, const H5HG_heap_t *heap, size_t *size_ptr) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_compute_size); - - /* Check arguments */ - HDassert(heap); - HDassert(size_ptr); - - *size_ptr = heap->size; - - FUNC_LEAVE_NOAPI(SUCCEED); -} /* H5HG_compute_size() */ - - -/*------------------------------------------------------------------------- * Function: H5HG_alloc * * Purpose: Given a heap with enough free space, this function will split @@ -714,7 +332,7 @@ H5HG_alloc (H5F_t *f, H5HG_heap_t *heap, size_t size, unsigned * heap_flags_ptr) /* Reallocate array of objects */ if (NULL==(new_obj = H5FL_SEQ_REALLOC (H5HG_obj_t, heap->obj, new_alloc))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed"); + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed") /* Update heap information */ heap->nalloc=new_alloc; @@ -803,75 +421,60 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HG_extend (H5F_t *f, H5HG_heap_t *heap, size_t size, unsigned * heap_flags_ptr) +H5HG_extend(H5F_t *f, H5HG_heap_t *heap, size_t need, unsigned *heap_flags_ptr) { - size_t need; /* Actual space needed to store object */ size_t old_size; /* Previous size of the heap's chunk */ - uint8_t *new_chunk=NULL; /* Pointer to new chunk information */ + uint8_t *new_chunk = NULL; /* Pointer to new chunk information */ uint8_t *p = NULL; /* Pointer to raw heap info */ unsigned u; /* Local index variable */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HG_extend); + FUNC_ENTER_NOAPI_NOINIT(H5HG_extend) /* Check args */ - assert (f); - assert (heap); - assert (heap_flags_ptr); - - /* Compute total space need to add to this heap */ - need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(size); - - /* Decrement the amount needed in the heap by the amount of free space available */ - assert(need>heap->obj[0].size); - need -= heap->obj[0].size; - - /* Don't do anything less than double the size of the heap */ - need = MAX(heap->size,need); - - /* Extend the space allocated for this heap on disk */ - if(H5MF_extend(f,H5FD_MEM_GHEAP,heap->addr,(hsize_t)heap->size,(hsize_t)need)<0) - HGOTO_ERROR (H5E_HEAP, H5E_NOSPACE, FAIL, "can't extend heap on disk"); + HDassert(f); + HDassert(heap); + HDassert(heap_flags_ptr); /* Re-allocate the heap information in memory */ - if (NULL==(new_chunk = H5FL_BLK_REALLOC (heap_chunk, heap->chunk, heap->size+need))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "new heap allocation failed"); + if(NULL == (new_chunk = H5FL_BLK_REALLOC(gheap_chunk, heap->chunk, (heap->size + need)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "new heap allocation failed") #ifdef H5_CLEAR_MEMORY HDmemset(new_chunk + heap->size, 0, need); #endif /* H5_CLEAR_MEMORY */ /* Adjust the size of the heap */ - old_size=heap->size; - heap->size+=need; + old_size = heap->size; + heap->size += need; /* Encode the new size of the heap */ p = new_chunk + H5_SIZEOF_MAGIC + 1 /* version */ + 3 /* reserved */; - H5F_ENCODE_LENGTH (f, p, heap->size); + H5F_ENCODE_LENGTH(f, p, heap->size); /* Move the pointers to the existing objects to their new locations */ - for (u=0; u<heap->nused; u++) + for(u = 0; u < heap->nused; u++) if(heap->obj[u].begin) heap->obj[u].begin = new_chunk + (heap->obj[u].begin - heap->chunk); /* Update the heap chunk pointer now */ - heap->chunk=new_chunk; + heap->chunk = new_chunk; /* Update the free space information for the heap */ - heap->obj[0].size+=need; - if(heap->obj[0].begin==NULL) - heap->obj[0].begin=heap->chunk+old_size; + heap->obj[0].size += need; + if(heap->obj[0].begin == NULL) + heap->obj[0].begin = heap->chunk+old_size; p = heap->obj[0].begin; UINT16ENCODE(p, 0); /*id*/ UINT16ENCODE(p, 0); /*nrefs*/ UINT32ENCODE(p, 0); /*reserved*/ - H5F_ENCODE_LENGTH (f, p, heap->obj[0].size); + H5F_ENCODE_LENGTH(f, p, heap->obj[0].size); assert(H5HG_ISALIGNED(heap->obj[0].size)); /* Mark the heap as dirty */ *heap_flags_ptr |= H5AC__DIRTIED_FLAG; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HG_extend() */ @@ -922,26 +525,26 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*/) +H5HG_insert(H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*/) { size_t need; /*total space needed for object */ - int cwfsno; + int cwfsno; size_t idx; haddr_t addr = HADDR_UNDEF; H5HG_heap_t *heap = NULL; unsigned heap_flags = H5AC__NO_FLAGS_SET; - hbool_t found=0; /* Flag to indicate a heap with enough space was found */ - herr_t ret_value=SUCCEED; /* Return value */ + hbool_t found = FALSE; /* Flag to indicate a heap with enough space was found */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5HG_insert, FAIL); + FUNC_ENTER_NOAPI(H5HG_insert, FAIL) /* Check args */ - assert (f); - assert (0==size || obj); - assert (hobj); + HDassert(f); + HDassert(0 == size || obj); + HDassert(hobj); - if (0==(f->intent & H5F_ACC_RDWR)) - HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file"); + if(0 == (f->intent & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file") /* Find a large enough collection on the CWFS list */ need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(size); @@ -970,20 +573,18 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out* * take any of it as gospel. * JRM - 5/24/04 */ - - for (cwfsno=0; cwfsno<f->shared->ncwfs; cwfsno++) { - if (f->shared->cwfs[cwfsno]->obj[0].size>=need) { + for(cwfsno = 0; cwfsno < f->shared->ncwfs; cwfsno++) + if(f->shared->cwfs[cwfsno]->obj[0].size >= need) { addr = f->shared->cwfs[cwfsno]->addr; - found=1; + found = TRUE; break; } /* end if */ - } /* end for */ /* * If we didn't find any collection with enough free space the check if * we can extend any of the collections to make enough room. */ - if (!found) { + if(!found) { size_t new_need; for (cwfsno=0; cwfsno<f->shared->ncwfs; cwfsno++) { @@ -991,12 +592,19 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out* new_need -= f->shared->cwfs[cwfsno]->obj[0].size; new_need = MAX(f->shared->cwfs[cwfsno]->size, new_need); - if((f->shared->cwfs[cwfsno]->size+new_need)<=H5HG_MAXSIZE && H5MF_can_extend(f,H5FD_MEM_GHEAP,f->shared->cwfs[cwfsno]->addr,(hsize_t)f->shared->cwfs[cwfsno]->size,(hsize_t)new_need)) { - if(H5HG_extend(f,f->shared->cwfs[cwfsno],size, &heap_flags)<0) - HGOTO_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL, "unable to extend global heap collection"); - addr = f->shared->cwfs[cwfsno]->addr; - found=1; - break; + if((f->shared->cwfs[cwfsno]->size + new_need) <= H5HG_MAXSIZE) { + htri_t extended; /* Whether the heap was extended */ + + extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_GHEAP, f->shared->cwfs[cwfsno]->addr, (hsize_t)f->shared->cwfs[cwfsno]->size, (hsize_t)new_need); + if(extended < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "error trying to extend heap") + else if(extended == TRUE) { + if(H5HG_extend(f, f->shared->cwfs[cwfsno], new_need, &heap_flags) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to extend global heap collection") + addr = f->shared->cwfs[cwfsno]->addr; + found = TRUE; + break; + } /* end if */ } /* end if */ } /* end for */ } /* end if */ @@ -1005,43 +613,40 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out* * If we didn't find any collection with enough free space then allocate a * new collection large enough for the message plus the collection header. */ - if (!found) { - + if(!found) { addr = H5HG_create(f, dxpl_id, need+H5HG_SIZEOF_HDR (f)); - if ( ! H5F_addr_defined(addr) ) - HGOTO_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL, \ - "unable to allocate a global heap collection"); + if(!H5F_addr_defined(addr)) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to allocate a global heap collection") cwfsno = 0; } /* end if */ else { - /* Move the collection forward in the CWFS list, if it's not * already at the front */ - if (cwfsno>0) { + if(cwfsno > 0) { H5HG_heap_t *tmp = f->shared->cwfs[cwfsno]; - f->shared->cwfs[cwfsno] = f->shared->cwfs[cwfsno-1]; - f->shared->cwfs[cwfsno-1] = tmp; + + f->shared->cwfs[cwfsno] = f->shared->cwfs[cwfsno - 1]; + f->shared->cwfs[cwfsno - 1] = tmp; --cwfsno; } /* end if */ } /* end else */ HDassert(H5F_addr_defined(addr)); - - if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_WRITE)) ) - HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); + if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") /* Split the free space to make room for the new object */ - idx = H5HG_alloc (f, heap, size, &heap_flags); + idx = H5HG_alloc(f, heap, size, &heap_flags); /* Copy data into the heap */ - if(size>0) { - HDmemcpy(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f), obj, size); + if(size > 0) { + HDmemcpy(heap->obj[idx].begin + H5HG_SIZEOF_OBJHDR(f), obj, size); #ifdef OLD_WAY /* Don't bother zeroing out the rest of the info in the heap -QAK */ - HDmemset(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f)+size, 0, - need-(H5HG_SIZEOF_OBJHDR(f)+size)); + HDmemset(heap->obj[idx].begin + H5HG_SIZEOF_OBJHDR(f) + size, 0, + need - (H5HG_SIZEOF_OBJHDR(f) + size)); #endif /* OLD_WAY */ } /* end if */ heap_flags |= H5AC__DIRTIED_FLAG; @@ -1051,10 +656,10 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out* hobj->idx = idx; done: - if ( heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, heap->addr, heap, heap_flags) < 0 ) - HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to unprotect heap."); + if(heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, heap->addr, heap, heap_flags) < 0) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to unprotect heap.") - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5HG_insert() */ @@ -1180,19 +785,19 @@ H5HG_link (H5F_t *f, hid_t dxpl_id, const H5HG_t *hobj, int adjust) assert (f); assert (hobj); if (0==(f->intent & H5F_ACC_RDWR)) - HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file"); + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file") if(adjust!=0) { /* Load the heap */ if (NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") assert (hobj->idx<heap->nused); assert (heap->obj[hobj->idx].begin); if (heap->obj[hobj->idx].nrefs+adjust<0) - HGOTO_ERROR (H5E_HEAP, H5E_BADRANGE, FAIL, "new link count would be out of range"); + HGOTO_ERROR (H5E_HEAP, H5E_BADRANGE, FAIL, "new link count would be out of range") if (heap->obj[hobj->idx].nrefs+adjust>H5HG_MAXLINK) - HGOTO_ERROR (H5E_HEAP, H5E_BADVALUE, FAIL, "new link count would be out of range"); + HGOTO_ERROR (H5E_HEAP, H5E_BADVALUE, FAIL, "new link count would be out of range") heap->obj[hobj->idx].nrefs += adjust; heap_flags |= H5AC__DIRTIED_FLAG; } /* end if */ @@ -1202,7 +807,7 @@ H5HG_link (H5F_t *f, hid_t dxpl_id, const H5HG_t *hobj, int adjust) done: if (heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, heap_flags)<0) - HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header"); + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header") FUNC_LEAVE_NOAPI(ret_value); } @@ -1230,88 +835,88 @@ done: herr_t H5HG_remove (H5F_t *f, hid_t dxpl_id, H5HG_t *hobj) { - uint8_t *p=NULL, *obj_start=NULL; H5HG_heap_t *heap = NULL; + uint8_t *p = NULL, *obj_start = NULL; size_t need; - int i; unsigned u; - unsigned flags=H5AC__NO_FLAGS_SET;/* Whether the heap gets deleted */ - herr_t ret_value=SUCCEED; /* Return value */ + unsigned flags = H5AC__NO_FLAGS_SET;/* Whether the heap gets deleted */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HG_remove, FAIL); /* Check args */ - assert (f); - assert (hobj); - if (0==(f->intent & H5F_ACC_RDWR)) - HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file"); + HDassert(f); + HDassert(hobj); + if(0 == (f->intent & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file") /* Load the heap */ - if (NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); + if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") - assert (hobj->idx<heap->nused); - assert (heap->obj[hobj->idx].begin); + HDassert(hobj->idx < heap->nused); + HDassert(heap->obj[hobj->idx].begin); obj_start = heap->obj[hobj->idx].begin; /* Include object header size */ - need = H5HG_ALIGN(heap->obj[hobj->idx].size)+H5HG_SIZEOF_OBJHDR(f); + need = H5HG_ALIGN(heap->obj[hobj->idx].size) + H5HG_SIZEOF_OBJHDR(f); /* Move the new free space to the end of the heap */ - for (u=0; u<heap->nused; u++) { - if (heap->obj[u].begin > heap->obj[hobj->idx].begin) + for(u = 0; u < heap->nused; u++) + if(heap->obj[u].begin > heap->obj[hobj->idx].begin) heap->obj[u].begin -= need; - } - if (NULL==heap->obj[0].begin) { - heap->obj[0].begin = heap->chunk + (heap->size-need); + if(NULL == heap->obj[0].begin) { + heap->obj[0].begin = heap->chunk + (heap->size - need); heap->obj[0].size = need; heap->obj[0].nrefs = 0; - } else { + } /* end if */ + else heap->obj[0].size += need; - } - HDmemmove (obj_start, obj_start+need, - heap->size-((obj_start+need)-heap->chunk)); - if (heap->obj[0].size>=H5HG_SIZEOF_OBJHDR (f)) { + HDmemmove(obj_start, obj_start + need, + heap->size - ((obj_start + need) - heap->chunk)); + if(heap->obj[0].size >= H5HG_SIZEOF_OBJHDR(f)) { p = heap->obj[0].begin; UINT16ENCODE(p, 0); /*id*/ UINT16ENCODE(p, 0); /*nrefs*/ UINT32ENCODE(p, 0); /*reserved*/ H5F_ENCODE_LENGTH (f, p, heap->obj[0].size); - } - HDmemset (heap->obj+hobj->idx, 0, sizeof(H5HG_obj_t)); + } /* end if */ + HDmemset(heap->obj + hobj->idx, 0, sizeof(H5HG_obj_t)); flags |= H5AC__DIRTIED_FLAG; - if (heap->obj[0].size+H5HG_SIZEOF_HDR(f)==heap->size) { + if((heap->obj[0].size + H5HG_SIZEOF_HDR(f)) == heap->size) { /* * The collection is empty. Remove it from the CWFS list and return it * to the file free list. */ - H5_CHECK_OVERFLOW(heap->size,size_t,hsize_t); - H5MF_xfree(f, H5FD_MEM_GHEAP, dxpl_id, heap->addr, (hsize_t)heap->size); - flags |= H5C__DELETED_FLAG; /* Indicate that the object was deleted, for the unprotect call */ - } else { + H5_CHECK_OVERFLOW(heap->size, size_t, hsize_t); + flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; /* Indicate that the object was deleted, for the unprotect call */ + } /* end if */ + else { + int i; /* Local index variable */ + /* * If the heap is in the CWFS list then advance it one position. The * H5AC_protect() might have done that too, but that's okay. If the * heap isn't on the CWFS list then add it to the end. */ - for (i=0; i<f->shared->ncwfs; i++) { - if (f->shared->cwfs[i]==heap) { - if (i) { - f->shared->cwfs[i] = f->shared->cwfs[i-1]; - f->shared->cwfs[i-1] = heap; - } + for(i = 0; i < f->shared->ncwfs; i++) + if(f->shared->cwfs[i] == heap) { + if(i) { + f->shared->cwfs[i] = f->shared->cwfs[i - 1]; + f->shared->cwfs[i - 1] = heap; + } /* end if */ break; - } - } - if (i>=f->shared->ncwfs) { - f->shared->ncwfs = MIN (f->shared->ncwfs+1, H5HG_NCWFS); - f->shared->cwfs[f->shared->ncwfs-1] = heap; - } - } + } /* end if */ + if(i >= f->shared->ncwfs) { + f->shared->ncwfs = MIN(f->shared->ncwfs + 1, H5HG_NCWFS); + f->shared->cwfs[f->shared->ncwfs - 1] = heap; + } /* end if */ + } /* end else */ done: - if (heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, flags) != SUCCEED) - HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header"); + if(heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, flags) < 0) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header") FUNC_LEAVE_NOAPI(ret_value); -} +} /* end H5HG_remove() */ + diff --git a/src/H5HGcache.c b/src/H5HGcache.c new file mode 100644 index 0000000..1a9e92c --- /dev/null +++ b/src/H5HGcache.c @@ -0,0 +1,442 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5HGcache.c + * Feb 5 2008 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: Implement global heap metadata cache methods. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5HG_PACKAGE /*suppress error about including H5HGpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5HGpkg.h" /* Global heaps */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5MMprivate.h" /* Memory management */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Metadata cache callbacks */ +static H5HG_heap_t *H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, + void *udata2); +static herr_t H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, + H5HG_heap_t *heap, unsigned UNUSED * flags_ptr); +static herr_t H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy); +static herr_t H5HG_size(const H5F_t *f, const H5HG_heap_t *heap, size_t *size_ptr); + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* H5HG inherits cache-like properties from H5AC */ +const H5AC_class_t H5AC_GHEAP[1] = {{ + H5AC_GHEAP_ID, + (H5AC_load_func_t)H5HG_load, + (H5AC_flush_func_t)H5HG_flush, + (H5AC_dest_func_t)H5HG_dest, + (H5AC_clear_func_t)H5HG_clear, + (H5AC_size_func_t)H5HG_size, +}}; + + + +/*------------------------------------------------------------------------- + * Function: H5HG_load + * + * Purpose: Loads a global heap collection from disk. + * + * Return: Success: Ptr to a global heap collection. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Friday, March 27, 1998 + * + *------------------------------------------------------------------------- + */ +static H5HG_heap_t * +H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, + void UNUSED * udata2) +{ + H5HG_heap_t *heap = NULL; + uint8_t *p = NULL; + size_t nalloc, need; + size_t max_idx = 0; /* The maximum index seen */ + H5HG_heap_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI(H5HG_load, NULL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(!udata1); + HDassert(!udata2); + + /* Read the initial 4k page */ + if(NULL == (heap = H5FL_CALLOC(H5HG_heap_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + heap->addr = addr; + if(NULL == (heap->chunk = H5FL_BLK_MALLOC(gheap_chunk, (size_t)H5HG_MINSIZE))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + if(H5F_block_read(f, H5FD_MEM_GHEAP, addr, (size_t)H5HG_MINSIZE, dxpl_id, heap->chunk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection") + + /* Magic number */ + if(HDmemcmp(heap->chunk, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad global heap collection signature") + p = heap->chunk + H5_SIZEOF_MAGIC; + + /* Version */ + if(H5HG_VERSION != *p++) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap") + + /* Reserved */ + p += 3; + + /* Size */ + H5F_DECODE_LENGTH(f, p, heap->size); + HDassert(heap->size >= H5HG_MINSIZE); + + /* + * If we didn't read enough in the first try, then read the rest of the + * collection now. + */ + if(heap->size > H5HG_MINSIZE) { + haddr_t next_addr = addr + (hsize_t)H5HG_MINSIZE; + + if(NULL == (heap->chunk = H5FL_BLK_REALLOC(gheap_chunk, heap->chunk, heap->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + if(H5F_block_read(f, H5FD_MEM_GHEAP, next_addr, (heap->size - H5HG_MINSIZE), dxpl_id, heap->chunk + H5HG_MINSIZE) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection") + } /* end if */ + + /* Decode each object */ + p = heap->chunk + H5HG_SIZEOF_HDR(f); + nalloc = H5HG_NOBJS(f, heap->size); + if(NULL == (heap->obj = H5FL_SEQ_MALLOC(H5HG_obj_t, nalloc))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + heap->obj[0].size = heap->obj[0].nrefs = 0; + heap->obj[0].begin = NULL; + + heap->nalloc = nalloc; + while(p < (heap->chunk + heap->size)) { + if((p + H5HG_SIZEOF_OBJHDR(f)) > (heap->chunk + heap->size)) { + /* + * The last bit of space is too tiny for an object header, so we + * assume that it's free space. + */ + HDassert(NULL == heap->obj[0].begin); + heap->obj[0].size = (heap->chunk + heap->size) - p; + heap->obj[0].begin = p; + p += heap->obj[0].size; + } /* end if */ + else { + unsigned idx; + uint8_t *begin = p; + + UINT16DECODE(p, idx); + + /* Check if we need more room to store heap objects */ + if(idx >= heap->nalloc) { + size_t new_alloc; /* New allocation number */ + H5HG_obj_t *new_obj; /* New array of object descriptions */ + + /* Determine the new number of objects to index */ + new_alloc = MAX(heap->nalloc * 2, (idx + 1)); + + /* Reallocate array of objects */ + if(NULL == (new_obj = H5FL_SEQ_REALLOC(H5HG_obj_t, heap->obj, new_alloc))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Update heap information */ + heap->nalloc = new_alloc; + heap->obj = new_obj; + } /* end if */ + + UINT16DECODE(p, heap->obj[idx].nrefs); + p += 4; /*reserved*/ + H5F_DECODE_LENGTH(f, p, heap->obj[idx].size); + heap->obj[idx].begin = begin; + + /* + * The total storage size includes the size of the object header + * and is zero padded so the next object header is properly + * aligned. The last bit of space is the free space object whose + * size is never padded and already includes the object header. + */ + if(idx > 0) { + need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(heap->obj[idx].size); + + /* Check for "gap" in index numbers (caused by deletions) and fill in heap object values */ + if(idx > (max_idx + 1)) + HDmemset(&heap->obj[max_idx + 1], 0, sizeof(H5HG_obj_t) * (idx - (max_idx + 1))); + max_idx = idx; + } /* end if */ + else + need = heap->obj[idx].size; + p = begin + need; + } /* end else */ + } /* end while */ + HDassert(p == heap->chunk + heap->size); + HDassert(H5HG_ISALIGNED(heap->obj[0].size)); + + /* Set the next index value to use */ + if(max_idx > 0) + heap->nused = max_idx + 1; + else + heap->nused = 1; + + /* + * Add the new heap to the CWFS list, removing some other entry if + * necessary to make room. We remove the right-most entry that has less + * free space than this heap. + */ + if(!f->shared->cwfs) { + f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5HG_NCWFS * sizeof(H5HG_heap_t *)); + if(NULL == f->shared->cwfs) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + f->shared->ncwfs = 1; + f->shared->cwfs[0] = heap; + } else if(H5HG_NCWFS == f->shared->ncwfs) { + int i; /* Local index variable */ + + for(i = H5HG_NCWFS - 1; i >= 0; --i) + if(f->shared->cwfs[i]->obj[0].size < heap->obj[0].size) { + HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, i * sizeof(H5HG_heap_t *)); + f->shared->cwfs[0] = heap; + break; + } /* end if */ + } else { + HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, f->shared->ncwfs * sizeof(H5HG_heap_t *)); + f->shared->ncwfs += 1; + f->shared->cwfs[0] = heap; + } /* end else */ + + ret_value = heap; + +done: + if(!ret_value && heap) + if(H5HG_dest(f, heap) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy global heap collection") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HG_load() */ + + +/*------------------------------------------------------------------------- + * Function: H5HG_flush + * + * Purpose: Flushes a global heap collection from memory to disk if it's + * dirty. Optionally deletes teh heap from memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, March 27, 1998 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HG_heap_t *heap, unsigned UNUSED * flags_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5HG_flush, FAIL) + + /* Check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(H5F_addr_eq(addr, heap->addr)); + HDassert(heap); + + if(heap->cache_info.is_dirty) { + if(H5F_block_write(f, H5FD_MEM_GHEAP, addr, heap->size, dxpl_id, heap->chunk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write global heap collection to file") + heap->cache_info.is_dirty = FALSE; + } /* end if */ + + if(destroy) + if(H5HG_dest(f, heap) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HG_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5HG_dest + * + * Purpose: Destroys a global heap collection in memory + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, January 15, 2003 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HG_dest(H5F_t *f, H5HG_heap_t *heap) +{ + int i; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HG_dest) + + /* Check arguments */ + HDassert(heap); + + /* Verify that node is clean */ + HDassert(heap->cache_info.is_dirty == FALSE); + + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!heap->cache_info.free_file_space_on_destroy || H5F_addr_defined(heap->cache_info.addr)); + + /* Check for freeing file space for globalheap */ + if(heap->cache_info.free_file_space_on_destroy) { + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_GHEAP, H5AC_dxpl_id, heap->cache_info.addr, (hsize_t)heap->size) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free global heap") + } /* end if */ + + /* Remove heap from NCWFS array, if it's present */ + for(i = 0; i < f->shared->ncwfs; i++) + if(f->shared->cwfs[i] == heap) { + f->shared->ncwfs -= 1; + HDmemmove(f->shared->cwfs + i, f->shared->cwfs + i + 1, (f->shared->ncwfs - i) * sizeof(H5HG_heap_t *)); + break; + } /* end if */ + + /* Release resources */ + if(heap->chunk) + heap->chunk = H5FL_BLK_FREE(gheap_chunk, heap->chunk); + if(heap->obj) + heap->obj = H5FL_SEQ_FREE(H5HG_obj_t, heap->obj); + (void)H5FL_FREE(H5HG_heap_t, heap); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HG_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5HG_clear + * + * Purpose: Mark a global heap in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Thursday, March 20, 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5HG_clear) + + /* Check arguments */ + HDassert(heap); + + /* Mark heap as clean */ + heap->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5HG_dest(f, heap) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HG_clear() */ + + +/*------------------------------------------------------------------------- + * Function: H5HG_size + * + * Purpose: Compute the size in bytes of the specified instance of + * H5HG_heap_t on disk, and return it in *len_ptr. On failure, + * the value of *len_ptr is undefined. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/13/04 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HG_size(const H5F_t UNUSED *f, const H5HG_heap_t *heap, size_t *size_ptr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_size) + + /* Check arguments */ + HDassert(heap); + HDassert(size_ptr); + + *size_ptr = heap->size; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HG_size() */ + diff --git a/src/H5HGpkg.h b/src/H5HGpkg.h index e814367..96be009 100644 --- a/src/H5HGpkg.h +++ b/src/H5HGpkg.h @@ -32,6 +32,9 @@ #include "H5HGprivate.h" /* Other private headers needed by this file */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5FLprivate.h" /* Free lists */ + /*****************************/ /* Package Private Variables */ @@ -40,11 +43,40 @@ /* The cache subclass */ H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1]; +/* Declare extern the free list to manage the H5HG_t struct */ +H5FL_EXTERN(H5HG_heap_t); + +/* Declare extern the free list to manage sequences of H5HG_obj_t's */ +H5FL_SEQ_EXTERN(H5HG_obj_t); + +/* Declare extern the PQ free list to manage heap chunks */ +H5FL_BLK_EXTERN(gheap_chunk); + + /**************************/ /* Package Private Macros */ /**************************/ /* + * Global heap collection version. + */ +#define H5HG_VERSION 1 + +/* + * All global heap collections are at least this big. This allows us to read + * most collections with a single read() since we don't have to read a few + * bytes of header to figure out the size. If the heap is larger than this + * then a second read gets the rest after we've decoded the header. + */ +#define H5HG_MINSIZE 4096 + +/* + * Maximum length of the CWFS list, the list of remembered collections that + * have free space. + */ +#define H5HG_NCWFS 16 + +/* * Pad all global heap messages to a multiple of eight bytes so we can load * the entire collection into memory and operate on it there. Eight should * be sufficient for machines that have alignment constraints because our @@ -56,6 +88,16 @@ H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1]; #define H5HG_ISALIGNED(X) ((X)==H5HG_ALIGN(X)) /* + * The size of the collection header, always a multiple of the alignment so + * that the stuff that follows the header is aligned. + */ +#define H5HG_SIZEOF_HDR(f) \ + H5HG_ALIGN(4 + /*magic number */ \ + 1 + /*version number */ \ + 3 + /*reserved */ \ + H5F_SIZEOF_SIZE(f)) /*collection size */ + +/* * The overhead associated with each object in the heap, always a multiple of * the alignment so that the stuff that follows the header is aligned. */ @@ -65,6 +107,17 @@ H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1]; 4 + /*reserved */ \ H5F_SIZEOF_SIZE(f)) /*object data size */ +/* + * The initial guess for the number of messages in a collection. We assume + * that all objects in that collection are zero length, giving the maximum + * possible number of objects in the collection. The collection itself has + * some overhead and each message has some overhead. The `+2' accounts for + * rounding and for the free space object. + */ +#define H5HG_NOBJS(f,z) (int)((((z)-H5HG_SIZEOF_HDR(f))/ \ + H5HG_SIZEOF_OBJHDR(f)+2)) + + /****************************/ /* Package Private Typedefs */ /****************************/ @@ -92,6 +145,7 @@ struct H5HG_heap_t { /******************************/ /* Package Private Prototypes */ /******************************/ +H5_DLL herr_t H5HG_dest(H5F_t *f, H5HG_heap_t *heap); -#endif +#endif /* _H5HGpkg_H */ @@ -22,69 +22,75 @@ * Purpose: Heap functions for the local heaps used by symbol * tables to store names (among other things). * - * Modifications: - * - * Robb Matzke, 5 Aug 1997 - * Added calls to H5E. - * *------------------------------------------------------------------------- */ + +/****************/ +/* Module Setup */ +/****************/ + #define H5F_PACKAGE /* Suppress error about including H5Fpkg */ #define H5HL_PACKAGE /* Suppress error about including H5HLpkg */ +/***********/ +/* Headers */ +/***********/ #include "H5private.h" /* Generic Functions */ -#include "H5ACprivate.h" /* Metadata cache */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ -#include "H5FLprivate.h" /* Free lists */ #include "H5HLpkg.h" /* Local Heaps */ #include "H5MFprivate.h" /* File memory management */ -/* Private macros */ -#define H5HL_FREE_NULL 1 /*end of free list on disk */ + +/****************/ +/* Local Macros */ +/****************/ + #define H5HL_MIN_HEAP 128 /* Minimum size to reduce heap buffer to */ -/* - * Local heap collection version. - */ -#define H5HL_VERSION 0 -/* Private typedefs */ +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ -/* PRIVATE PROTOTYPES */ -static herr_t H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf); static H5HL_free_t *H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl); static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap); -/* Metadata cache callbacks */ -static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, - void *udata2); -static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr); -static herr_t H5HL_dest(H5F_t *f, H5HL_t *heap); -static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy); -static herr_t H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr); -/* - * H5HL inherits cache-like properties from H5AC - */ -const H5AC_class_t H5AC_LHEAP[1] = {{ - H5AC_LHEAP_ID, - (H5AC_load_func_t)H5HL_load, - (H5AC_flush_func_t)H5HL_flush, - (H5AC_dest_func_t)H5HL_dest, - (H5AC_clear_func_t)H5HL_clear, - (H5AC_size_func_t)H5HL_size, -}}; +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ /* Declare a free list to manage the H5HL_free_t struct */ -H5FL_DEFINE_STATIC(H5HL_free_t); +H5FL_DEFINE(H5HL_free_t); /* Declare a free list to manage the H5HL_t struct */ -H5FL_DEFINE_STATIC(H5HL_t); +H5FL_DEFINE(H5HL_t); /* Declare a PQ free list to manage the heap chunk information */ -H5FL_BLK_DEFINE_STATIC(heap_chunk); +H5FL_BLK_DEFINE(lheap_chunk); + /*------------------------------------------------------------------------- @@ -106,15 +112,6 @@ H5FL_BLK_DEFINE_STATIC(heap_chunk); * matzke@llnl.gov * Jul 16 1997 * - * Modifications: - * - * Robb Matzke, 5 Aug 1997 - * Takes a flag that determines the type of heap that is - * created. - * - * John Mainzer, 6/7/05 - * Removed code modifying the is_dirty field of the cache info. - * *------------------------------------------------------------------------- */ herr_t @@ -125,179 +122,58 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/) size_t sizeof_hdr; /* Cache H5HL header size for file */ herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(H5HL_create, FAIL); + FUNC_ENTER_NOAPI(H5HL_create, FAIL) /* check arguments */ - assert(f); - assert(addr_p); + HDassert(f); + HDassert(addr_p); - if (size_hint && size_hint < H5HL_SIZEOF_FREE(f)) + if(size_hint && size_hint < H5HL_SIZEOF_FREE(f)) size_hint = H5HL_SIZEOF_FREE(f); size_hint = H5HL_ALIGN(size_hint); /* Cache this for later */ - sizeof_hdr= H5HL_SIZEOF_HDR(f); + sizeof_hdr = H5HL_SIZEOF_HDR(f); /* allocate file version */ total_size = sizeof_hdr + size_hint; - if (HADDR_UNDEF==(*addr_p=H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file memory"); + if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file memory") /* allocate memory version */ - if (NULL==(heap = H5FL_CALLOC(H5HL_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + if(NULL == (heap = H5FL_CALLOC(H5HL_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") heap->addr = *addr_p + (hsize_t)sizeof_hdr; heap->heap_alloc = size_hint; - if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + size_hint)))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + size_hint)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* free list */ - if (size_hint) { - if (NULL==(heap->freelist = H5FL_MALLOC(H5HL_free_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + if(size_hint) { + if(NULL == (heap->freelist = H5FL_MALLOC(H5HL_free_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") heap->freelist->offset = 0; heap->freelist->size = size_hint; heap->freelist->prev = heap->freelist->next = NULL; - } else { + } /* end if */ + else heap->freelist = NULL; - } /* add to cache */ - if (H5AC_set(f, dxpl_id, H5AC_LHEAP, *addr_p, heap, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache heap"); + if(H5AC_set(f, dxpl_id, H5AC_LHEAP, *addr_p, heap, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache heap") done: - if (ret_value<0) { - if (H5F_addr_defined(*addr_p)) + if(ret_value < 0) { + if(H5F_addr_defined(*addr_p)) H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, *addr_p, total_size); - if (heap) { - if(H5HL_dest(f,heap)<0) - HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection"); - } - } - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5HL_load - * - * Purpose: Loads a heap from disk. - * - * Return: Success: Ptr to a local heap memory data structure. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 17 1997 - * - * Modifications: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - *------------------------------------------------------------------------- - */ -static H5HL_t * -H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, - void UNUSED * udata2) -{ - uint8_t hdr[52]; - size_t sizeof_hdr; /* Cache H5HL header size for file */ - const uint8_t *p = NULL; - H5HL_t *heap = NULL; - H5HL_free_t *fl = NULL, *tail = NULL; - size_t free_block = H5HL_FREE_NULL; - H5HL_t *ret_value; - - FUNC_ENTER_NOAPI(H5HL_load, NULL) - - /* check arguments */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); - HDassert(!udata1); - HDassert(!udata2); - - /* Cache this for later */ - 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") - p = hdr; - - /* Check magic number */ - if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC)) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap signature") - p += H5_SIZEOF_MAGIC; - - /* Version */ - 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") - - /* 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") - - /* 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 && - 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") - - /* 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") - fl->offset = free_block; - fl->prev = tail; - fl->next = NULL; - if(tail) - tail->next = fl; - tail = fl; - if(!heap->freelist) - heap->freelist = fl; - - p = heap->chunk + sizeof_hdr + free_block; - - H5F_DECODE_LENGTH(f, p, free_block); - 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") - } /* 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(heap) + if(H5HL_dest(f,heap) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection") + } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HL_load() */ +} /* end H5HL_create() */ /*------------------------------------------------------------------------- @@ -313,22 +189,6 @@ done: * wendling@ncsa.uiuc.edu * Sept. 16, 2003 * - * Modifications: - * - * John Mainzer, 8/10/05 - * Reworked this function for a different role. - * - * It used to be called during cache eviction, where it - * attempted to size the disk space allocation for the - * actual size of the heap. However, this causes problems - * in the parallel case, as the reuslting disk allocations - * may not be synchronized. - * - * It is now called from H5HL_remove(), where it is used to - * reduce heap size in response to an entry deletion. This - * means that the function should either do nothing, or - * reduce the size of the disk allocation. - * *------------------------------------------------------------------------- */ static herr_t @@ -429,15 +289,15 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) HDassert(new_heap_size < heap->heap_alloc); /* Resize the memory buffer */ - heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + new_heap_size)); + heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + new_heap_size)); if(!heap->chunk) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Release old space on disk */ /* (Should be safe to free old heap space first, since it's shrinking -QAK) */ H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); - H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc); - H5E_clear_stack(NULL); /* don't really care if the free failed */ + if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap") /* Allocate new space on disk */ H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t); @@ -455,268 +315,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5HL_serialize - * - * Purpose: Serialize the heap. This function will eliminate free - * blocks at the tail of the heap and also split the block - * if it needs to be split for the file. This is so that we - * can serialize it correctly. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Bill Wendling - * wendling@ncsa.uiuc.edu - * Sept. 16, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf) -{ - H5HL_free_t *fl; - uint8_t *p; - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_serialize) - - /* check args */ - assert(buf); - assert(heap); - - /* serialize the header */ - p = buf; - fl = heap->freelist; - HDmemcpy(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC); - p += H5_SIZEOF_MAGIC; - *p++ = H5HL_VERSION; - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - H5F_ENCODE_LENGTH(f, p, heap->heap_alloc); - H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL); - H5F_addr_encode(f, &p, heap->addr); - - /* serialize the free list */ - for (; fl; fl = fl->next) { - assert (fl->offset == H5HL_ALIGN (fl->offset)); - p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset; - - if (fl->next) { - H5F_ENCODE_LENGTH(f, p, fl->next->offset); - } else { - H5F_ENCODE_LENGTH(f, p, H5HL_FREE_NULL); - } - - H5F_ENCODE_LENGTH(f, p, fl->size); - } - - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5HL_flush - * - * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally - * deletes the heap from memory. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 17 1997 - * - * Modifications: - * rky, 1998-08-28 - * Only p0 writes metadata to disk. - * - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - * - * Bill Wendling, 2003-09-16 - * Separated out the bit that serializes the heap. - * - * John Mainzer, 2005-08-10 - * Removed call to H5HL_minimize_heap_space(). It does disk space - * allocation, which can cause problems if done at flush time. - * Instead, disk space allocation/deallocation is now done at - * insert/remove time. - * - * John Mainzer, 2006-08-21 - * Added the flags_ptr parameter. This parameter exists to - * allow the flush routine to report to the cache if the - * entry is resized or renamed as a result of the flush. - * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5HL_flush, FAIL); - - /* check arguments */ - HDassert( f ); - HDassert( H5F_addr_defined(addr) ); - HDassert( heap ); - - if (heap->cache_info.is_dirty) { - haddr_t hdr_end_addr; - size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */ - - /* Write the header */ - if (H5HL_serialize(f, heap, heap->chunk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "unable to serialize local heap") - - /* Copy buffer to disk */ - hdr_end_addr = addr + (hsize_t)sizeof_hdr; - - if (H5F_addr_eq(heap->addr, hdr_end_addr)) { - /* The header and data are contiguous */ - if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc), - dxpl_id, heap->chunk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file") - } else { - if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file") - - if (H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, - dxpl_id, heap->chunk + sizeof_hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file") - } - - heap->cache_info.is_dirty = FALSE; - } - - /* Should we destroy the memory version? */ - if (destroy) { - if (H5HL_dest(f,heap) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection") - } - -done: - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5HL_dest - * - * Purpose: Destroys a heap in memory. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jan 15 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HL_dest(H5F_t UNUSED *f, H5HL_t *heap) -{ - H5HL_free_t *fl; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_dest) - - /* check arguments */ - HDassert(heap); - - /* Verify that node is clean */ - HDassert(heap->cache_info.is_dirty == FALSE); - - if(heap->chunk) - heap->chunk = H5FL_BLK_FREE(heap_chunk, heap->chunk); - while(heap->freelist) { - fl = heap->freelist; - heap->freelist = fl->next; - (void)H5FL_FREE(H5HL_free_t, fl); - } /* end while */ - (void)H5FL_FREE(H5HL_t, heap); - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HL_dest() */ - - -/*------------------------------------------------------------------------- - * Function: H5HL_clear - * - * Purpose: Mark a local heap in memory as non-dirty. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 20 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5HL_clear); - - /* check arguments */ - assert(heap); - - /* Mark heap as clean */ - heap->cache_info.is_dirty = FALSE; - - if (destroy) - if (H5HL_dest(f, heap) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5HL_clear() */ - - -/*------------------------------------------------------------------------- - * Function: H5HL_size - * - * Purpose: Compute the size in bytes of the specified instance of - * H5HL_t on disk, and return it in *len_ptr. On failure, - * the value of *len_ptr is undefined. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: John Mainzer - * 5/13/04 - * - * Modifications: - *------------------------------------------------------------------------- - */ -static herr_t -H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_size); - - /* check arguments */ - HDassert(f); - HDassert(heap); - HDassert(size_ptr); - - *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HL_size() */ - - -/*------------------------------------------------------------------------- * Function: H5HL_protect * * Purpose: This function is a wrapper for the H5AC_protect call. The @@ -779,8 +377,6 @@ done: * wendling@ncsa.uiuc.edu * Sept. 17, 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ void * @@ -791,11 +387,13 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset) * valid heap pointer. So, this can remain "FUNC_ENTER_NOAPI_NOINIT" */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_offset_into) - assert(f); - assert(heap); - assert(offset < heap->heap_alloc); + + HDassert(f); + HDassert(heap); + HDassert(offset < heap->heap_alloc); + FUNC_LEAVE_NOAPI(heap->chunk + H5HL_SIZEOF_HDR(f) + offset) -} +} /* end H5HL_offset_into() */ /*------------------------------------------------------------------------- @@ -849,7 +447,7 @@ done: static H5HL_free_t * H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_remove_free); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_remove_free) if(fl->prev) fl->prev->next = fl->next; @@ -859,7 +457,7 @@ H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl) if(!fl->prev) heap->freelist = fl->next; - FUNC_LEAVE_NOAPI((H5HL_free_t *)H5FL_FREE(H5HL_free_t, fl)); + FUNC_LEAVE_NOAPI((H5HL_free_t *)H5FL_FREE(H5HL_free_t, fl)) } /* end H5HL_remove_free() */ @@ -949,9 +547,9 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * * free chunk. If the heap must expand, we double its size. */ if(found == FALSE) { - size_t need_more; /* How much more space we need */ - size_t new_heap_alloc; /* Final size of space allocated for heap */ - htri_t can_extend; /* Whether the local heap's data segment on disk can be extended */ + size_t need_more; /* How much more space we need */ + size_t new_heap_alloc; /* Final size of space allocated for heap */ + htri_t extended; /* Whether the local heap's data segment on disk was extended */ /* At least double the heap's size, making certain there's enough room * for the new object */ @@ -1011,34 +609,21 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); H5_CHECK_OVERFLOW(new_heap_alloc, size_t, hsize_t); - /* Check if current heap is extendible */ - can_extend = H5MF_can_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more); - if(can_extend < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to check whether heap can be extended") + /* Extend current heap if possible */ + extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more); + if(extended < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, (size_t)(-1), "error trying to extend heap") - /* extend the current heap if we can... */ - if(can_extend == TRUE) { - if(H5MF_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "can't extend heap on disk") - } /* end if */ - else { /* ...if we can't, allocate a new chunk & release the old */ - haddr_t new_addr; - - /* The new allocation may fail -- to avoid the possiblity of - * file corruption, allocate the new heap first, and then - * deallocate the old. - */ + /* If we couldn't extend the heap, release old chunk and allocate a new one */ + if(extended == FALSE) { + /* Release old space on disk */ + if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, (size_t)(-1), "unable to free local heap") /* allocate new disk space for the heap */ - if((new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_alloc)) == HADDR_UNDEF) + if((heap->addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_alloc)) == HADDR_UNDEF) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to allocate file space for heap") - - /* Release old space on disk */ - H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc); - H5E_clear_stack(NULL); /* don't really care if the free failed */ - - heap->addr = new_addr; - } /* end else */ + } /* end if */ /* If the last free list in the heap is at the end of the heap, extend it */ if(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc) { @@ -1096,7 +681,7 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void * } #endif heap->heap_alloc = new_heap_alloc; - heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc)); + heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc)); if(NULL == heap->chunk) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed") @@ -1148,7 +733,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size) H5HL_free_t *fl = NULL; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5HL_remove, FAIL); + FUNC_ENTER_NOAPI(H5HL_remove, FAIL) /* check arguments */ HDassert(f); @@ -1272,7 +857,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size) } /* end if */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HL_remove() */ @@ -1287,67 +872,33 @@ done: * koziol@ncsa.uiuc.edu * Mar 22 2003 * - * Modifications: - * - * John Mainzer - 6/17/05 - * Modified function to use the new dirtied parmeter of - * H5AC_unprotect(), which allows management of the is_dirty - * field of the cache info to be moved into the cache code. - * *------------------------------------------------------------------------- */ herr_t H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) { - H5HL_t *heap = NULL; - size_t sizeof_hdr; /* Cache H5HL header size for file */ - herr_t ret_value=SUCCEED; /* Return value */ + H5HL_t *heap = NULL; /* Local heap to delete */ + unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5HL_delete, FAIL); + FUNC_ENTER_NOAPI(H5HL_delete, FAIL) /* check arguments */ - assert(f); - assert(H5F_addr_defined(addr)); - - /* Cache this for later */ - sizeof_hdr= H5HL_SIZEOF_HDR(f); + HDassert(f); + HDassert(H5F_addr_defined(addr)); /* Get heap pointer */ - if (NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); - - /* Check if the heap is contiguous on disk */ - assert(!H5F_addr_overflow(addr,sizeof_hdr)); - if(H5F_addr_eq(heap->addr,addr+sizeof_hdr)) { - /* Free the contiguous local heap in one call */ - H5_CHECK_OVERFLOW(sizeof_hdr+heap->heap_alloc,size_t,hsize_t); - if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)(sizeof_hdr+heap->heap_alloc))<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap"); - } /* end if */ - else { - /* Free the local heap's header */ - H5_CHECK_OVERFLOW(sizeof_hdr,size_t,hsize_t); - if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)sizeof_hdr)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header"); - - /* Free the local heap's data */ - H5_CHECK_OVERFLOW(heap->heap_alloc,size_t,hsize_t); - if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data"); - } /* end else */ - - /* Release the local heap metadata from the cache */ - if (H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG)<0) { - heap = NULL; - HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap"); - } - heap = NULL; + if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") + + /* Set the cache flags to delete the heap & free its file space */ + cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; done: - if (heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__NO_FLAGS_SET)<0) - HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap"); + if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, cache_flags) < 0) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap") - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5HL_delete() */ diff --git a/src/H5HLcache.c b/src/H5HLcache.c new file mode 100644 index 0000000..449e166 --- /dev/null +++ b/src/H5HLcache.c @@ -0,0 +1,478 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5HLcache.c + * Feb 5 2008 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: Implement local heap metadata cache methods. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5HL_PACKAGE /* Suppress error about including H5HLpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5HLpkg.h" /* Local Heaps */ +#include "H5MFprivate.h" /* File memory management */ + + +/****************/ +/* Local Macros */ +/****************/ + +#define H5HL_VERSION 0 /* Local heap collection version */ +#define H5HL_FREE_NULL 1 /* End of free list on disk */ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Local encode/decode routines */ +static herr_t H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf); + +/* Metadata cache callbacks */ +static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, + void *udata2); +static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr); +static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy); + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* H5HL inherits cache-like properties from H5AC */ +const H5AC_class_t H5AC_LHEAP[1] = {{ + H5AC_LHEAP_ID, + (H5AC_load_func_t)H5HL_load, + (H5AC_flush_func_t)H5HL_flush, + (H5AC_dest_func_t)H5HL_dest, + (H5AC_clear_func_t)H5HL_clear, + (H5AC_size_func_t)H5HL_size, +}}; + + +/*------------------------------------------------------------------------- + * Function: H5HL_serialize + * + * Purpose: Serialize the heap. This function will eliminate free + * blocks at the tail of the heap and also split the block + * if it needs to be split for the file. This is so that we + * can serialize it correctly. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Bill Wendling + * wendling@ncsa.uiuc.edu + * Sept. 16, 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf) +{ + H5HL_free_t *fl; + uint8_t *p; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_serialize) + + /* check args */ + assert(buf); + assert(heap); + + /* serialize the header */ + p = buf; + fl = heap->freelist; + HDmemcpy(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC); + p += H5_SIZEOF_MAGIC; + *p++ = H5HL_VERSION; + *p++ = 0; /*reserved*/ + *p++ = 0; /*reserved*/ + *p++ = 0; /*reserved*/ + H5F_ENCODE_LENGTH(f, p, heap->heap_alloc); + H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL); + H5F_addr_encode(f, &p, heap->addr); + + /* serialize the free list */ + for (; fl; fl = fl->next) { + assert (fl->offset == H5HL_ALIGN (fl->offset)); + p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset; + + if (fl->next) { + H5F_ENCODE_LENGTH(f, p, fl->next->offset); + } else { + H5F_ENCODE_LENGTH(f, p, H5HL_FREE_NULL); + } + + H5F_ENCODE_LENGTH(f, p, fl->size); + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_serialize() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_load + * + * Purpose: Loads a heap from disk. + * + * Return: Success: Ptr to a local heap memory data structure. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 17 1997 + * + *------------------------------------------------------------------------- + */ +static H5HL_t * +H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, + void UNUSED * udata2) +{ + uint8_t hdr[52]; + size_t sizeof_hdr; /* Cache H5HL header size for file */ + const uint8_t *p = NULL; + H5HL_t *heap = NULL; + H5HL_free_t *fl = NULL, *tail = NULL; + size_t free_block = H5HL_FREE_NULL; + H5HL_t *ret_value; + + FUNC_ENTER_NOAPI(H5HL_load, NULL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(!udata1); + HDassert(!udata2); + + /* Cache this for later */ + 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") + p = hdr; + + /* Check magic number */ + if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap signature") + p += H5_SIZEOF_MAGIC; + + /* Version */ + 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") + + /* 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") + + /* data */ + H5F_addr_decode(f, &p, &(heap->addr)); + if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_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") + + /* 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") + fl->offset = free_block; + fl->prev = tail; + fl->next = NULL; + if(tail) + tail->next = fl; + tail = fl; + if(!heap->freelist) + heap->freelist = fl; + + p = heap->chunk + sizeof_hdr + free_block; + + H5F_DECODE_LENGTH(f, p, free_block); + 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") + } /* 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") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_load() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_flush + * + * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally + * deletes the heap from memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 17 1997 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5HL_flush, FAIL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(heap); + + if(heap->cache_info.is_dirty) { + haddr_t hdr_end_addr; + size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */ + + /* Write the header */ + if(H5HL_serialize(f, heap, heap->chunk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "unable to serialize local heap") + + /* Copy buffer to disk */ + hdr_end_addr = addr + (hsize_t)sizeof_hdr; + + if(H5F_addr_eq(heap->addr, hdr_end_addr)) { + /* The header and data are contiguous */ + if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc), dxpl_id, heap->chunk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file") + } /* end if */ + else { + if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file") + + if(H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file") + } /* end else */ + + heap->cache_info.is_dirty = FALSE; + } /* end if */ + + /* Should we destroy the memory version? */ + if(destroy) + if(H5HL_dest(f, heap) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_dest + * + * Purpose: Destroys a heap in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 15 2003 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HL_dest(H5F_t *f, H5HL_t *heap) +{ + H5HL_free_t *fl; /* Heap object free list */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HL_dest) + + /* check arguments */ + HDassert(heap); + + /* Verify that node is clean */ + HDassert(heap->cache_info.is_dirty == FALSE); + + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!heap->cache_info.free_file_space_on_destroy || H5F_addr_defined(heap->cache_info.addr)); + + /* Check for freeing file space for local heap */ + if(heap->cache_info.free_file_space_on_destroy) { + size_t sizeof_hdr; /* H5HL header size for file */ + haddr_t hdr_addr; /* Address of heap header in file */ + + /* Compute this for later */ + sizeof_hdr = H5HL_SIZEOF_HDR(f); + hdr_addr = heap->cache_info.addr; + + /* Check if the heap is contiguous on disk */ + HDassert(!H5F_addr_overflow(hdr_addr, sizeof_hdr)); + if(H5F_addr_eq(heap->addr, hdr_addr + sizeof_hdr)) { + /* Free the contiguous local heap in one call */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + H5_CHECK_OVERFLOW(sizeof_hdr + heap->heap_alloc, size_t, hsize_t); + if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, hdr_addr, (hsize_t)(sizeof_hdr + heap->heap_alloc)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap") + } /* end if */ + else { + /* Free the local heap's header */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + H5_CHECK_OVERFLOW(sizeof_hdr, size_t, hsize_t); + if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, hdr_addr, (hsize_t)sizeof_hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header") + + /* Free the local heap's data */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); + if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, heap->addr, (hsize_t)heap->heap_alloc) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data") + } /* end else */ + } /* end if */ + + /* Release resources */ + if(heap->chunk) + heap->chunk = H5FL_BLK_FREE(lheap_chunk, heap->chunk); + while(heap->freelist) { + fl = heap->freelist; + heap->freelist = fl->next; + (void)H5FL_FREE(H5HL_free_t, fl); + } /* end while */ + (void)H5FL_FREE(H5HL_t, heap); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_clear + * + * Purpose: Mark a local heap in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 20 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HL_clear) + + /* check arguments */ + HDassert(heap); + + /* Mark heap as clean */ + heap->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5HL_dest(f, heap) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_clear() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL_size + * + * Purpose: Compute the size in bytes of the specified instance of + * H5HL_t on disk, and return it in *len_ptr. On failure, + * the value of *len_ptr is undefined. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/13/04 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_size) + + /* check arguments */ + HDassert(f); + HDassert(heap); + HDassert(size_ptr); + + *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HL_size() */ + diff --git a/src/H5HLpkg.h b/src/H5HLpkg.h index 48781e3..1e34a48 100644 --- a/src/H5HLpkg.h +++ b/src/H5HLpkg.h @@ -32,6 +32,9 @@ #include "H5HLprivate.h" /* Other private headers needed by this file */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5FLprivate.h" /* Free lists */ + /*****************************/ /* Package Private Variables */ @@ -40,6 +43,16 @@ /* The cache subclass */ H5_DLLVAR const H5AC_class_t H5AC_LHEAP[1]; +/* Declare extern the free list to manage the H5HL_free_t struct */ +H5FL_EXTERN(H5HL_free_t); + +/* Declare extern the free list to manage the H5HL_t struct */ +H5FL_EXTERN(H5HL_t); + +/* Declare extern the PQ free list to manage the heap chunk information */ +H5FL_BLK_EXTERN(lheap_chunk); + + /**************************/ /* Package Private Macros */ /**************************/ @@ -51,6 +64,7 @@ H5_DLLVAR const H5AC_class_t H5AC_LHEAP[1]; H5F_SIZEOF_SIZE (F) + /*free list head */ \ H5F_SIZEOF_ADDR (F)) /*data address */ + /****************************/ /* Package Private Typedefs */ /****************************/ @@ -71,10 +85,13 @@ struct H5HL_t { H5HL_free_t *freelist; /*the free list */ }; + /******************************/ /* Package Private Prototypes */ /******************************/ -#endif +H5_DLL herr_t H5HL_dest(H5F_t *f, H5HL_t *heap); +H5_DLL herr_t H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr); +#endif /* _H5HLpkg_H */ @@ -29,6 +29,7 @@ /****************/ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5MF_PACKAGE /*suppress error about including H5MFpkg */ /***********/ @@ -37,18 +38,33 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ -#include "H5MFprivate.h" /* File memory management */ +#include "H5MFpkg.h" /* File memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ /****************/ /* Local Macros */ /****************/ +#define H5MF_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */ +#define H5MF_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */ + +/* Map an allocation request type to a free list */ +#define H5MF_ALLOC_TO_FS_TYPE(F, T) ((H5FD_MEM_DEFAULT == (F)->shared->fs_type_map[T]) \ + ? (T) : (F)->shared->fs_type_map[T]) + /******************/ /* Local Typedefs */ /******************/ +/* Enum for kind of free space section+aggregator merging allowed for a file */ +typedef enum { + H5MF_AGGR_MERGE_SEPARATE, /* Everything in separate free list */ + H5MF_AGGR_MERGE_DICHOTOMY, /* Metadata in one free list and raw data in another */ + H5MF_AGGR_MERGE_TOGETHER /* Metadata & raw data in one free list */ +} H5MF_aggr_merge_t; + /********************/ /* Package Typedefs */ @@ -58,7 +74,6 @@ /********************/ /* Local Prototypes */ /********************/ -static hbool_t H5MF_alloc_overflow(H5F_t *f, hsize_t size); /*********************/ @@ -77,6 +92,177 @@ static hbool_t H5MF_alloc_overflow(H5F_t *f, hsize_t size); /*------------------------------------------------------------------------- + * Function: H5MF_init_merge_flags + * + * Purpose: Initialize the free space section+aggregator merge flags + * for the file. + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * Friday, February 1, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5MF_init_merge_flags(H5F_t *f) +{ + H5MF_aggr_merge_t mapping_type; /* Type of free list mapping */ + H5FD_mem_t type; /* Memory type for iteration */ + hbool_t all_same; /* Whether all the types map to the same value */ + + FUNC_ENTER_NOAPI_NOFUNC(H5MF_init_merge_flags) + + /* check args */ + HDassert(f); + HDassert(f->shared); + HDassert(f->shared->lf); + + /* Iterate over all the free space types to determine if sections of that type + * can merge with the metadata or small 'raw' data aggregator + */ + all_same = TRUE; + for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) + /* Check for any different type mappings */ + if(f->shared->fs_type_map[type] != f->shared->fs_type_map[H5FD_MEM_DEFAULT]) { + all_same = FALSE; + break; + } /* end if */ + + /* Check for all allocation types mapping to the same free list type */ + if(all_same) { + if(f->shared->fs_type_map[H5FD_MEM_DEFAULT] == H5FD_MEM_DEFAULT) + mapping_type = H5MF_AGGR_MERGE_SEPARATE; + else + mapping_type = H5MF_AGGR_MERGE_TOGETHER; + } /* end if */ + else { + /* Check for raw data mapping into same list as metadata */ + if(f->shared->fs_type_map[H5FD_MEM_DRAW] == f->shared->fs_type_map[H5FD_MEM_SUPER]) + mapping_type = H5MF_AGGR_MERGE_SEPARATE; + else { + hbool_t all_metadata_same; /* Whether all metadata go in same free list */ + + /* One or more allocation type don't map to the same free list type */ + /* Check if all the metadata allocation types map to the same type */ + all_metadata_same = TRUE; + for(type = H5FD_MEM_SUPER; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) + /* Skip checking raw data free list mapping */ + if(type != H5FD_MEM_DRAW) { + /* Check for any different type mappings */ + if(f->shared->fs_type_map[type] != f->shared->fs_type_map[H5FD_MEM_SUPER]) { + all_metadata_same = FALSE; + break; + } /* end if */ + } /* end if */ + + /* Check for all metadata on same free list */ + if(all_metadata_same) + mapping_type = H5MF_AGGR_MERGE_DICHOTOMY; + else + mapping_type = H5MF_AGGR_MERGE_SEPARATE; + } /* end else */ + } /* end else */ + + /* Based on mapping type, initialize merging flags for each free list type */ + switch(mapping_type) { + case H5MF_AGGR_MERGE_SEPARATE: + HDmemset(f->shared->fs_aggr_merge, 0, sizeof(f->shared->fs_aggr_merge)); + break; + + case H5MF_AGGR_MERGE_DICHOTOMY: + HDmemset(f->shared->fs_aggr_merge, H5F_FS_MERGE_METADATA, sizeof(f->shared->fs_aggr_merge)); + f->shared->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA; + break; + + case H5MF_AGGR_MERGE_TOGETHER: + HDmemset(f->shared->fs_aggr_merge, (H5F_FS_MERGE_METADATA | H5F_FS_MERGE_RAWDATA), sizeof(f->shared->fs_aggr_merge)); + break; + } /* end switch */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5MF_init_merge_flags() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_alloc_start + * + * Purpose: "Start up" free space for file - open existing free space + * structure if one exists, otherwise create a new free space + * structure + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jan 8 2008 + * + * Modifications: + * Vailin Choi, July 29th, 2008 + * Pass values of alignment and threshold to FS_create() for handling alignment + * + *------------------------------------------------------------------------- + */ +herr_t +H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, hbool_t may_create) +{ + const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for file */ + H5MF_FSPACE_SECT_CLS_SIMPLE}; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5MF_alloc_start) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(f->shared); + + /* Check for creating free space info for the file */ + if(H5F_addr_defined(f->shared->fs_addr[type])) { + /* Open an existing free space structure for the file */ + HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED); + if(NULL == (f->shared->fs_man[type] = H5FS_open(f, dxpl_id, f->shared->fs_addr[type], + NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info") + } /* end if */ + else { + /* 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_FILE_ID; + fs_create.shrink_percent = H5MF_FSPACE_SHRINK; + fs_create.expand_percent = H5MF_FSPACE_EXPAND; + fs_create.max_sect_addr = 1 + H5V_log2_gen((uint64_t)f->shared->maxaddr); + fs_create.max_sect_size = f->shared->maxaddr; + + /* Create the free space structure for the heap */ + HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED); +#ifdef LATER + if(NULL == (f->shared->fs_man[type] = H5FS_create(f, dxpl_id, &f->shared->fs_addr[type], + &fs_create, NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info") +#else /* LATER */ + if(NULL == (f->shared->fs_man[type] = H5FS_create(f, dxpl_id, NULL, + &fs_create, NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info") +#endif /* LATER */ + } /* end if */ + } /* end else */ + + /* Set the state for the free space manager to "open", if it is now */ + if(f->shared->fs_man[type]) + f->shared->fs_state[type] = H5F_FS_STATE_OPEN; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_alloc_start() */ + + +/*------------------------------------------------------------------------- * Function: H5MF_alloc * * Purpose: Allocate SIZE bytes of file memory and return the relative @@ -94,31 +280,105 @@ static hbool_t H5MF_alloc_overflow(H5F_t *f, hsize_t size); *------------------------------------------------------------------------- */ haddr_t -H5MF_alloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) +H5MF_alloc(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, hsize_t size) { - haddr_t ret_value; + H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */ + haddr_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5MF_alloc, HADDR_UNDEF) +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", FUNC, (unsigned)alloc_type, size); +#endif /* H5MF_ALLOC_DEBUG */ /* check arguments */ 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") - - /* 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") - - /* Convert absolute file address to relative file address */ - HDassert(ret_value >= f->shared->base_addr); - - /* Set return value */ - ret_value -= f->shared->base_addr; + /* Get free space type from allocation type */ + fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type); + + /* Check if the free space manager for the file has been initialized */ + if(!f->shared->fs_man[fs_type]) + if(H5MF_alloc_start(f, dxpl_id, fs_type, FALSE) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "can't initialize file free space") + + /* Search for large enough space in the free space manager */ + if(f->shared->fs_man[fs_type]) { + H5MF_free_section_t *node; /* Free space section pointer */ + htri_t node_found = FALSE; /* Whether an existing free list node was found */ + + /* Try to get a section from the free space manager */ + if((node_found = H5FS_sect_find(f, dxpl_id, f->shared->fs_man[fs_type], size, (H5FS_section_info_t **)&node)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "error locating free space in file") +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Check 1.5, node_found = %t\n", FUNC, node_found); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* Check for actually finding section */ + if(node_found) { + /* Sanity check */ + HDassert(node); + + /* Retrieve return value */ + ret_value = node->sect_info.addr; + + /* Check for eliminating the section */ + if(node->sect_info.size == size) { +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Check 1.6, freeing node\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + /* Free section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, HADDR_UNDEF, "can't free simple section node") + } /* end if */ + else { + H5MF_sect_ud_t udata; /* User data for callback */ + + /* Adjust information for section */ + node->sect_info.addr += size; + node->sect_info.size -= size; + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.alloc_type = alloc_type; + udata.allow_sect_absorb = TRUE; + +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Check 1.7, re-adding node, node->sect_info.size = %Hu\n", FUNC, node->sect_info.size); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + /* Re-insert section node into file's free space */ + if(H5FS_sect_add(f, dxpl_id, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, HADDR_UNDEF, "can't re-add section to file free space") + } /* end else */ + + /* Leave now */ + HGOTO_DONE(ret_value) + } /* end if */ + } /* end if */ +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Check 2.0\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* Couldn't find anything from the free space manager, go allocate some */ + if(alloc_type != H5FD_MEM_DRAW) { + /* Handle metadata differently from "raw" data */ + if(HADDR_UNDEF == (ret_value = H5MF_aggr_alloc(f, dxpl_id, &(f->shared->meta_aggr), &(f->shared->sdata_aggr), alloc_type, size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata") + } /* end if */ + else { + /* Allocate "raw" data */ + if(HADDR_UNDEF == (ret_value = H5MF_aggr_alloc(f, dxpl_id, &(f->shared->sdata_aggr), &(f->shared->meta_aggr), alloc_type, size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data") + } /* end else */ done: +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Leaving: ret_value = %a, size = %Hu\n", FUNC, ret_value, size); +#endif /* H5MF_ALLOC_DEBUG */ +#ifdef H5MF_ALLOC_DEBUG_DUMP +H5MF_sects_dump(f, dxpl_id, stderr); +#endif /* H5MF_ALLOC_DEBUG_DUMP */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5MF_alloc() */ @@ -138,193 +398,458 @@ done: *------------------------------------------------------------------------- */ herr_t -H5MF_xfree(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size) +H5MF_xfree(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, haddr_t addr, + hsize_t size) { - herr_t ret_value = SUCCEED; /* Return value */ + H5MF_free_section_t *node = NULL; /* Free space section pointer */ + H5MF_sect_ud_t udata; /* User data for callback */ + H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5MF_xfree) + FUNC_ENTER_NOAPI(H5MF_xfree, FAIL) +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)alloc_type, addr, size); +#endif /* H5MF_ALLOC_DEBUG */ /* check arguments */ HDassert(f); if(!H5F_addr_defined(addr) || 0 == size) HGOTO_DONE(SUCCEED); - 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) { -#ifdef H5MF_DEBUG - if(H5DEBUG(MF)) - fprintf(H5DEBUG(MF), "H5MF_free: lost %lu bytes of file storage\n", (unsigned long)size); -#endif + HDassert(addr != 0); /* Can't deallocate the superblock :-) */ + + /* Check if the space to free intersects with the file's metadata accumulator */ + if(H5F_accum_free(f, dxpl_id, alloc_type, addr, size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't check free space intersection w/metadata accumulator") + + /* Get free space type from allocation type */ + fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type); +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: fs_type = %u\n", FUNC, (unsigned)fs_type); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* Check if the free space manager for the file has been initialized */ + if(!f->shared->fs_man[fs_type]) { + /* If there's no free space manager for objects of this type, + * see if we can avoid creating one by checking if the freed + * space is at the end of the file + */ +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)fs_type, f->shared->fs_addr[fs_type]); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + if(!H5F_addr_defined(f->shared->fs_addr[fs_type])) { + htri_t status; /* "can absorb" status for section into */ + +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Trying to avoid starting up free space manager\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + /* Try to shrink the file or absorb the block into a block aggregator */ + if((status = H5MF_try_shrink(f, alloc_type, dxpl_id, addr, size)) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for absorbing block") + else if(status > 0) + /* Indicate success */ + HGOTO_DONE(SUCCEED) + } /* end if */ + + /* If we are deleting the free space manager, leave now, to avoid + * [re-]starting it. + * + * Note: this drops the space to free on the floor... + * + */ + if(f->shared->fs_state[fs_type] == H5F_FS_STATE_DELETING) +{ +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: dropping addr = %a, size = %Hu, on the floor!\n", FUNC, addr, size); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + HGOTO_DONE(SUCCEED) +} + + /* There's either already a free space manager, or the freed + * space isn't at the end of the file, so start up (or create) + * the file space manager + */ + if(H5MF_alloc_start(f, dxpl_id, fs_type, TRUE) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space") } /* end if */ + HDassert(f->shared->fs_man[fs_type]); + + /* Create free space section for block */ + if(NULL == (node = H5MF_sect_simple_new(addr, size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section") + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.alloc_type = alloc_type; + udata.allow_sect_absorb = TRUE; + + /* Add to the free space for the file */ +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Before H5FS_sect_add()\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + if(H5FS_sect_add(f, dxpl_id, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't add section to file free space") +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: After H5FS_sect_add()\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + node = NULL; done: + if(ret_value < 0 && node) + /* On error, free section node allocated */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node") + +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value); +#endif /* H5MF_ALLOC_DEBUG */ +#ifdef H5MF_ALLOC_DEBUG_DUMP +H5MF_sects_dump(f, dxpl_id, stderr); +#endif /* H5MF_ALLOC_DEBUG_DUMP */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5MF_xfree() */ /*------------------------------------------------------------------------- - * Function: H5MF_realloc + * Function: H5MF_try_extend * - * Purpose: Changes the size of an allocated chunk, possibly moving it to - * a new address. The chunk to change is at address OLD_ADDR - * and is exactly OLD_SIZE bytes (if these are H5F_ADDR_UNDEF - * and zero then this function acts like H5MF_alloc). The new - * size will be NEW_SIZE and its address is the return value (if - * NEW_SIZE is zero then this function acts like H5MF_free and - * an undefined address is returned). + * Purpose: Extend a block in the file if possible. * - * If the new size is less than the old size then the new - * address will be the same as the old address (except for the - * special case where the new size is zero). - * - * If the new size is more than the old size then most likely a - * new address will be returned. However, under certain - * circumstances the library may return the same address. - * - * Return: Success: The relative file address of the new block. - * Failure: HADDR_UNDEF + * Return: Success: TRUE(1) - Block was extended + * FALSE(0) - Block could not be extended + * Failure: FAIL * - * Programmer: Robb Matzke - * Thursday, April 16, 1998 + * Programmer: Quincey Koziol + * Friday, June 11, 2004 * *------------------------------------------------------------------------- */ -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) +htri_t +H5MF_try_extend(H5F_t *f, hid_t dxpl_id, H5FD_mem_t alloc_type, haddr_t addr, + hsize_t size, hsize_t extra_requested) { - haddr_t ret_value; - - FUNC_ENTER_NOAPI(H5MF_realloc, HADDR_UNDEF) - - /* Convert old relative address to absolute address */ - old_addr += f->shared->base_addr; - - /* 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") - - /* Convert return value to relative address */ - HDassert(ret_value >= f->shared->base_addr); + haddr_t end; /* End of block to extend */ + htri_t ret_value; /* Return value */ - /* Set return value */ - ret_value -= f->shared->base_addr; + FUNC_ENTER_NOAPI(H5MF_try_extend, FAIL) +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Entering: alloc_type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n", FUNC, (unsigned)alloc_type, addr, size, extra_requested); +#endif /* H5MF_ALLOC_DEBUG */ + + /* Compute end of block to extend */ + end = addr + size; + + /* Check if the block is exactly at the end of the file */ + if((ret_value = H5FD_try_extend(f->shared->lf, alloc_type, end, extra_requested)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending file") + else if(ret_value == FALSE) { + H5F_blk_aggr_t *aggr; /* Aggregator to use */ + + /* Check for test block able to extend aggregation block */ + aggr = (alloc_type == H5FD_MEM_DRAW) ? &(f->shared->sdata_aggr) : &(f->shared->meta_aggr); + if((ret_value = H5MF_aggr_try_extend(f, aggr, alloc_type, end, extra_requested)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending aggregation block") + else if(ret_value == FALSE) { + H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */ + + /* Get free space type from allocation type */ + fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type); + + /* Check if the free space for the file has been initialized */ + if(!f->shared->fs_man[fs_type]) + if(H5MF_alloc_start(f, dxpl_id, fs_type, FALSE) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space") + + /* Check for test block able to block in free space manager */ + if(f->shared->fs_man[fs_type]) + if((ret_value = H5FS_sect_try_extend(f, dxpl_id, f->shared->fs_man[fs_type], addr, size, extra_requested)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending block in free space manager") + } /* end if */ + } /* end if */ done: +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Leaving: ret_value = %t\n", FUNC, ret_value); +#endif /* H5MF_ALLOC_DEBUG */ +#ifdef H5MF_ALLOC_DEBUG_DUMP +H5MF_sects_dump(f, dxpl_id, stderr); +#endif /* H5MF_ALLOC_DEBUG_DUMP */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5MF_realloc() */ +} /* end H5MF_try_extend() */ /*------------------------------------------------------------------------- - * Function: H5MF_alloc_overflow + * Function: H5MF_get_freespace * - * Purpose: Checks if an allocation of file space would cause an overflow. - * F is the file whose space is being allocated, SIZE is the amount - * of space needed. + * Purpose: Retrieve the amount of free space in a file. * - * Return: FALSE if no overflow would result - * TRUE if overflow would result (the allocation should not be allowed) + * Return: Success: Amount of free space in file + * Failure: Negative * - * Programmer: James Laird - * Nat Furrer - * Tuesday, June 1, 2004 + * Programmer: Quincey Koziol + * Monday, October 6, 2003 * *------------------------------------------------------------------------- */ -static hbool_t -H5MF_alloc_overflow(H5F_t *f, hsize_t size) +hssize_t +H5MF_get_freespace(H5F_t *f, hid_t dxpl_id) { - 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_NOINIT_NOFUNC(H5MF_alloc_overflow) - - /* Start with the current end of the file's address. */ - eoa = H5F_get_eoa(f); - HDassert(H5F_addr_defined(eoa)); - - /* Subtract EOA from the file's maximum address to get the actual amount of - * addressable space left in the file. - */ - HDassert(f->shared->maxaddr >= eoa); - space_avail = (hsize_t)(f->shared->maxaddr - eoa); + haddr_t eoa; /* End of allocated space in the file */ + 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" */ + hsize_t tot_fs_size = 0; /* Amount of all free space managed */ + H5FD_mem_t type; /* Memory type for iteration */ + hssize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5MF_get_freespace, FAIL) + + /* check args */ + HDassert(f); + HDassert(f->shared); + HDassert(f->shared->lf); + + /* Retrieve the 'eoa' for the file */ + if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed") + + /* Retrieve metadata aggregator info, if available */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + /* Retrieve 'small data' aggregator info, if available */ + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size); + + /* Iterate over all the free space types that have managers and get each free list's space */ + for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) { + hsize_t type_fs_size = 0; /* Amount of free space managed for each type */ + + /* Check if the free space for the file has been initialized */ + if(!f->shared->fs_man[type]) + if(H5MF_alloc_start(f, dxpl_id, type, FALSE) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space") + + /* Retrieve free space size from free space manager */ + if(f->shared->fs_man[type]) + if((ret_value = H5FS_sect_stats(f->shared->fs_man[type], &type_fs_size, NULL)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query free space stats") + + /* Increment total free space for types */ + tot_fs_size += type_fs_size; + } /* end for */ + + /* Start computing value to return */ + ret_value = tot_fs_size; + + /* 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 */ - /* 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; + /* 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 H5MF_alloc_overflow() */ +} /* end H5MF_get_freespace() */ /*------------------------------------------------------------------------- - * Function: H5MF_can_extend + * Function: H5MF_can_shrink * - * Purpose: Check if a block in the file can be extended. + * Purpose: Try to shrink the size of a file with a block or absorb it + * into a block aggregator. * - * Return: Success: TRUE(1)/FALSE(0) - * Failure: FAIL + * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Friday, June 11, 2004 + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Feb 14 2008 * *------------------------------------------------------------------------- */ htri_t -H5MF_can_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested) +H5MF_try_shrink(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, haddr_t addr, + hsize_t size) { - htri_t ret_value; /* Return value */ + H5MF_free_section_t *node = NULL; /* Free space section pointer */ + H5MF_sect_ud_t udata; /* User data for callback */ + htri_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5MF_can_extend, FAIL) + FUNC_ENTER_NOAPI(H5MF_try_shrink, FAIL) +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)alloc_type, addr, size); +#endif /* H5MF_ALLOC_DEBUG */ - /* Convert old relative address to absolute address */ - addr += H5F_BASE_ADDR(f); + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(size > 0); - /* Pass the request down to the virtual file layer */ - 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"); + /* Create free space section for block */ + if(NULL == (node = H5MF_sect_simple_new(addr, size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section") + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.alloc_type = alloc_type; + udata.allow_sect_absorb = FALSE; /* Force section to be absorbed into aggregator */ + + /* Call the "can shrink" callback for the section */ + if((ret_value = H5MF_sect_simple_can_shrink((const H5FS_section_info_t *)node, &udata)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "can't check if section can shrink container") + else if(ret_value > 0) { + /* Shrink or absorb the section */ + if(H5MF_sect_simple_shrink((H5FS_section_info_t **)&node, &udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink container") + } /* end if */ done: + /* Free section node allocated */ + if(node && H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node") + +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value); +#endif /* H5MF_ALLOC_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5MF_can_extend() */ +} /* end H5MF_try_shrink() */ /*------------------------------------------------------------------------- - * Function: H5MF_extend + * Function: H5MF_close * - * Purpose: Extend a block in the file. + * Purpose: Close the free space tracker(s) for a file * - * Return: Success: Non-negative - * Failure: Negative + * Return: SUCCEED/FAIL * - * Programmer: Quincey Koziol - * Saturday, June 12, 2004 + * Programmer: Quincey Koziol + * Tuesday, January 22, 2008 * *------------------------------------------------------------------------- */ herr_t -H5MF_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested) +H5MF_close(H5F_t *f, hid_t dxpl_id) { - herr_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5MF_extend, FAIL) - - /* 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") + H5FD_mem_t type; /* Memory type for iteration */ + H5F_blk_aggr_t *first_aggr; /* First aggregator to reset */ + H5F_blk_aggr_t *second_aggr; /* Second aggregator to reset */ + 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" */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5MF_close, FAIL) +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Entering\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG */ + + /* check args */ + HDassert(f); + HDassert(f->shared); + HDassert(f->shared->lf); + + /* Iterate over all the free space types that have managers and get each free list's space */ + for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) { +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Check 1.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + /* If the free space manager for this type is open, close it */ + if(f->shared->fs_man[type]) { +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Before closing free space manager\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + if(H5FS_close(f, dxpl_id, f->shared->fs_man[type]) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info") + f->shared->fs_man[type] = NULL; + f->shared->fs_state[type] = H5F_FS_STATE_CLOSED; + } /* end if */ +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Check 2.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* If there is free space manager info for this type, delete it */ + /* (XXX: Make this optional when free space for a file can be persistant) */ + if(H5F_addr_defined(f->shared->fs_addr[type])) { + haddr_t tmp_fs_addr; /* Temporary holder for free space manager address */ + + /* Put address into temporary variable and reset it */ + /* (Avoids loopback in file space freeing routine) */ + tmp_fs_addr = f->shared->fs_addr[type]; + f->shared->fs_addr[type] = HADDR_UNDEF; + + /* Shift to "deleting" state, to make certain we don't track any + * file space freed as a result of deleting the free space manager. + */ + f->shared->fs_state[type] = H5F_FS_STATE_DELETING; + +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Before deleting free space manager\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + /* Delete free space manager for this type */ + if(H5FS_delete(f, dxpl_id, tmp_fs_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't delete free space manager") + + /* Shift [back] to closed state */ + HDassert(f->shared->fs_state[type] == H5F_FS_STATE_DELETING); + f->shared->fs_state[type] = H5F_FS_STATE_CLOSED; + + /* Sanity check that the free space manager for this type wasn't started up again */ + HDassert(!H5F_addr_defined(f->shared->fs_addr[type])); + } /* end if */ + } /* end for */ + + /* Retrieve metadata aggregator info, if available */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: ma_addr = %a, ma_size = %Hu, end of ma = %a\n", FUNC, ma_addr, ma_size, (haddr_t)((ma_addr + ma_size) - 1)); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* Retrieve 'small data' aggregator info, if available */ + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size); +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: sda_addr = %a, sda_size = %Hu, end of sda = %a\n", FUNC, sda_addr, sda_size, (haddr_t)((sda_addr + sda_size) - 1)); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* Make certain we release the aggregator that's later in the file first */ + /* (so the file shrinks properly) */ + if(H5F_addr_defined(ma_addr) && H5F_addr_defined(sda_addr)) { + if(H5F_addr_lt(ma_addr, sda_addr)) { + first_aggr = &(f->shared->sdata_aggr); + second_aggr = &(f->shared->meta_aggr); + } /* end if */ + else { + first_aggr = &(f->shared->meta_aggr); + second_aggr = &(f->shared->sdata_aggr); + } /* end else */ + } /* end if */ + else { + first_aggr = &(f->shared->meta_aggr); + second_aggr = &(f->shared->sdata_aggr); + } /* end else */ + + /* Release the unused portion of the metadata and "small data" blocks back + * to the free lists in the file. + */ + if(H5MF_aggr_reset(f, dxpl_id, first_aggr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't reset metadata block") + if(H5MF_aggr_reset(f, dxpl_id, second_aggr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't reset 'small data' block") done: +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Leaving\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5MF_extend() */ +} /* end H5MF_close() */ diff --git a/src/H5MFaggr.c b/src/H5MFaggr.c new file mode 100644 index 0000000..dda1968 --- /dev/null +++ b/src/H5MFaggr.c @@ -0,0 +1,571 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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> + * Tuesday, January 8, 2008 + * + * Purpose: Routines for aggregating free space allocations + * + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5MF_PACKAGE /*suppress error about including H5MFpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5MFpkg.h" /* File memory management */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5MF_aggr_alloc + * + * Purpose: Try to allocate SIZE bytes of memory from an aggregator + * block if possible. + * + * Return: Success: The format address of the new file memory. + * Failure: The undefined address HADDR_UNDEF + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 + * + * Modifications: + * Vailin Choi, July 29th, 2008 + * The whole routine is modified to handle alignment + * + *------------------------------------------------------------------------- + */ +haddr_t +H5MF_aggr_alloc(H5F_t *f, hid_t dxpl_id, H5F_blk_aggr_t *aggr, + H5F_blk_aggr_t *other_aggr, H5FD_mem_t type, hsize_t size) +{ + haddr_t ret_value; + hsize_t alignment = 0, mis_align = 0; + haddr_t frag_addr = 0, eoa_frag_addr = 0; + hsize_t frag_size = 0, eoa_frag_size = 0; + haddr_t eoa = 0, new_space = 0; + htri_t extended = 0; + H5FD_mem_t alloc_type, other_alloc_type; + + FUNC_ENTER_NOAPI(H5MF_aggr_alloc, HADDR_UNDEF) +#ifdef H5MF_AGGR_DEBUG +HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); +#endif /* H5MF_AGGR_DEBUG */ + + /* check args */ + HDassert(f); + 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 file, allocate "generic" + * space and sub-allocate out of that, if possible. Otherwise just allocate + * through H5FD_alloc() + */ + if(f->shared->feature_flags & aggr->feature_flag) { +#ifdef H5MF_AGGR_DEBUG +HDfprintf(stderr, "%s: aggr = {%a, %Hu, %Hu}\n", FUNC, aggr->addr, aggr->tot_size, aggr->size); +#endif /* H5MF_AGGR_DEBUG */ + + alignment = f->shared->alignment; + if (!((alignment > 1) && (size >= f->shared->threshold))) + alignment = 0; /* no alignment */ + + if (alignment && aggr->addr > 0 && aggr->size > 0 && (mis_align = aggr->addr % alignment)) { + frag_addr = aggr->addr; + frag_size = alignment - mis_align; + } + + if (HADDR_UNDEF == (eoa = H5F_get_eoa(f, type))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "Unable to get eoa") + + alloc_type = aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW; + other_alloc_type = other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW; + + /* Check if the space requested is larger than the space left in the block */ + if((size + frag_size) > aggr->size) { + + /* Check if the block asked for is too large for 'normal' aggregator block */ + if(size >= aggr->alloc_size) { + + hsize_t ext_size = size + frag_size; + + if ((aggr->addr > 0) && (extended=H5FD_try_extend(f->shared->lf, alloc_type, aggr->addr + aggr->size, ext_size)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't extending space") + else if (extended) { + /* aggr->size is unchanged */ + ret_value = aggr->addr + frag_size; + aggr->addr += ext_size; + aggr->tot_size += ext_size; + } else { + if ((other_aggr->size > 0) && (H5F_addr_eq((other_aggr->addr + other_aggr->size), eoa)) && + ((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size)) { + + if(H5FD_free(f->shared->lf, dxpl_id, other_alloc_type, other_aggr->addr, other_aggr->size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") + + other_aggr->addr = 0; + other_aggr->tot_size = 0; + other_aggr->size = 0; + } + + if(HADDR_UNDEF == (new_space = H5FD_alloc(f->shared->lf, dxpl_id, type, size, &eoa_frag_addr, &eoa_frag_size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block") + + /* Use the new space allocated, leaving the old block */ + ret_value = new_space; + } /* end else */ + } /* end if */ + else { + hsize_t ext_size = aggr->alloc_size; + + /* Allocate another block */ +#ifdef H5MF_AGGR_DEBUG +HDfprintf(stderr, "%s: Allocating block\n", FUNC); +#endif /* H5MF_AGGR_DEBUG */ + + if (frag_size > (ext_size - size)) + ext_size += (frag_size - (ext_size - size)); + + if ((aggr->addr > 0) && (extended = H5FD_try_extend(f->shared->lf, alloc_type, aggr->addr + aggr->size, ext_size)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't extending space") + else if (extended) { + aggr->addr += frag_size; + aggr->size += (ext_size - frag_size); + aggr->tot_size += ext_size; + } else { + haddr_t unused_addr = HADDR_UNDEF; /* Address of unused portion */ + hsize_t unused_size = 0; /* Size of unused portion */ + + if ((other_aggr->size > 0) && (H5F_addr_eq((other_aggr->addr + other_aggr->size), eoa)) && + ((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size)) { + + if(H5FD_free(f->shared->lf, dxpl_id, other_alloc_type, other_aggr->addr, other_aggr->size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") + other_aggr->addr = 0; + other_aggr->tot_size = 0; + other_aggr->size = 0; + } + + if(HADDR_UNDEF == (new_space = H5FD_alloc(f->shared->lf, dxpl_id, alloc_type, aggr->alloc_size, &eoa_frag_addr, &eoa_frag_size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block") + + /* Return the unused portion of the block to a free list */ + if(aggr->size > 0) + if(H5MF_xfree(f, alloc_type, dxpl_id, aggr->addr, aggr->size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") + + /* Point the aggregator at the newly allocated block */ + aggr->addr = new_space; + aggr->size = aggr->alloc_size; + aggr->tot_size = aggr->alloc_size; + + } /* end else */ + + /* Allocate space out of the metadata block */ + ret_value = aggr->addr; + aggr->size -= size; + aggr->addr += size; + } /* end else */ + + /* freeing any possible fragment due to file allocation */ + if (eoa_frag_size) + if(H5MF_xfree(f, type, dxpl_id, eoa_frag_addr, eoa_frag_size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free eoa fragment") + + /* freeing any possible fragment due to alignment in the block after extension */ + if (extended && frag_size) + if(H5MF_xfree(f, type, dxpl_id, frag_addr, frag_size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation fragment") + } /* end if */ + else { + /* Allocate space out of the block */ + ret_value = aggr->addr + frag_size; + aggr->size -= (size + frag_size); + aggr->addr += (size + frag_size); + + /* free any possible fragment */ + if (frag_size) + if(H5MF_xfree(f, type, dxpl_id, frag_addr, frag_size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation fragment") + } + } /* end if */ + else { + /* Allocate data from the file */ + if(HADDR_UNDEF == (ret_value = H5FD_alloc(f->shared->lf, dxpl_id, type, size, &eoa_frag_addr, &eoa_frag_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate file space") + if (eoa_frag_size) + if(H5MF_xfree(f, type, dxpl_id, eoa_frag_addr, eoa_frag_size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free eoa fragment") + } /* end else */ + +done: +#ifdef H5MF_AGGR_DEBUG +HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); +#endif /* H5MF_AGGR_DEBUG */ + if (alignment) + HDassert(!(ret_value % alignment)); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_aggr_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_aggr_try_extend + * + * Purpose: Check if a block is inside an aggregator block and extend it + * if possible. + * + * Return: Success: TRUE(1) - Block was extended + * FALSE(0) - Block could not be extended + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 + * + *------------------------------------------------------------------------- + */ +htri_t +H5MF_aggr_try_extend(const H5F_t *f, H5F_blk_aggr_t *aggr, H5FD_mem_t type, + haddr_t blk_end, hsize_t extra_requested) +{ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(H5MF_aggr_try_extend, FAIL) + + /* Check args */ + HDassert(f); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + + /* Check if this aggregator is active */ + if(f->shared->feature_flags & aggr->feature_flag) { + /* If the block being tested adjoins the beginning of the aggregator + * block, check if the aggregator can accomodate the extension. + */ + if(H5F_addr_eq(blk_end, aggr->addr)) { + /* If the aggregator block is at the end of the file, extend the + * file and "bubble" the aggregator up + */ + if((ret_value = H5FD_try_extend(f->shared->lf, type, (aggr->addr + aggr->size), extra_requested)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending file") + else if(ret_value == TRUE) { + /* Shift the aggregator block by the extra requested */ + aggr->addr += extra_requested; + + /* Add extra requested to the aggregator block's total amount allocated */ + aggr->tot_size += extra_requested; + } /* end if */ + else { + /* Check if the aggregator block has enough internal space to satisfy + * extending the block. + */ + if(aggr->size >= extra_requested) { + /* Extend block into aggregator */ + aggr->size -= extra_requested; + aggr->addr += extra_requested; + + /* Indicate success */ + HGOTO_DONE(TRUE); + } /* end if */ + } /* end else */ + } /* end if */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_aggr_try_extend() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_aggr_can_absorb + * + * Purpose: Check if a section adjoins an aggregator block and one can + * absorb the other. + * + * Return: Success: TRUE(1) - Section or aggregator can be absorbed + * FALSE(0) - Section and aggregator can not be absorbed + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Friday, February 1, 2008 + * + *------------------------------------------------------------------------- + */ +htri_t +H5MF_aggr_can_absorb(const H5F_t *f, const H5F_blk_aggr_t *aggr, + const H5MF_free_section_t *sect, H5MF_shrink_type_t *shrink) +{ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOFUNC(H5MF_aggr_can_absorb) + + /* Check args */ + HDassert(f); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + HDassert(sect); + HDassert(shrink); + + /* Check if this aggregator is active */ + if(f->shared->feature_flags & aggr->feature_flag) { + /* Check if the block adjoins the beginning or end of the aggregator */ + if(H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr) + || H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr)) { +#ifdef H5MF_AGGR_DEBUG +HDfprintf(stderr, "%s: section {%a, %Hu} adjoins aggr = {%a, %Hu}\n", "H5MF_aggr_can_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size); +#endif /* H5MF_AGGR_DBEUG */ + /* Check if aggregator would get too large and should be absorbed into section */ + if((aggr->size + sect->sect_info.size) >= aggr->alloc_size) + *shrink = H5MF_SHRINK_SECT_ABSORB_AGGR; + else + *shrink = H5MF_SHRINK_AGGR_ABSORB_SECT; + + /* Indicate success */ + HGOTO_DONE(TRUE) + } /* end if */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_aggr_can_absorb() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_aggr_absorb + * + * Purpose: Absorb a free space section into an aggregator block or + * vice versa. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Friday, February 1, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5MF_aggr_absorb(const H5F_t *f, H5F_blk_aggr_t *aggr, H5MF_free_section_t *sect, + hbool_t allow_sect_absorb) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5MF_aggr_absorb) + + /* Check args */ + HDassert(f); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + HDassert(f->shared->feature_flags & aggr->feature_flag); + HDassert(sect); + + /* Check if aggregator would get too large and should be absorbed into section */ + if((aggr->size + sect->sect_info.size) >= aggr->alloc_size && allow_sect_absorb) { + /* Check if the section adjoins the beginning or end of the aggregator */ + if(H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr)) { +#ifdef H5MF_AGGR_DBEUG +HDfprintf(stderr, "%s: aggr {%a, %Hu} adjoins front of section = {%a, %Hu}\n", "H5MF_aggr_absorb", aggr->addr, aggr->size, sect->sect_info.addr, sect->sect_info.size); +#endif /* H5MF_AGGR_DBEUG */ + /* Absorb aggregator onto end of section */ + sect->sect_info.size += aggr->size; + } /* end if */ + else { + /* Sanity check */ + HDassert(H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr)); + +#ifdef H5MF_AGGR_DBEUG +HDfprintf(stderr, "%s: aggr {%a, %Hu} adjoins end of section = {%a, %Hu}\n", "H5MF_aggr_absorb", aggr->addr, aggr->size, sect->sect_info.addr, sect->sect_info.size); +#endif /* H5MF_AGGR_DBEUG */ + /* Absorb aggregator onto beginning of section */ + sect->sect_info.addr -= aggr->size; + sect->sect_info.size += aggr->size; + } /* end if */ + + /* Reset aggregator */ + aggr->tot_size = 0; + aggr->addr = 0; + aggr->size = 0; + } /* end if */ + else { + /* Check if the section adjoins the beginning or end of the aggregator */ + if(H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr)) { +#ifdef H5MF_AGGR_DBEUG +HDfprintf(stderr, "%s: section {%a, %Hu} adjoins front of aggr = {%a, %Hu}\n", "H5MF_aggr_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size); +#endif /* H5MF_AGGR_DBEUG */ + /* Absorb section onto front of aggregator */ + aggr->addr -= sect->sect_info.size; + aggr->size += sect->sect_info.size; + + /* Sections absorbed onto front of aggregator count against the total + * amount of space aggregated together. + */ + aggr->tot_size -= MIN(aggr->tot_size, sect->sect_info.size); + } /* end if */ + else { + /* Sanity check */ + HDassert(H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr)); + +#ifdef H5MF_AGGR_DBEUG +HDfprintf(stderr, "%s: section {%a, %Hu} adjoins end of aggr = {%a, %Hu}\n", "H5MF_aggr_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size); +#endif /* H5MF_AGGR_DBEUG */ + /* Absorb section onto end of aggregator */ + aggr->size += sect->sect_info.size; + } /* end if */ + /* Sanity check */ + HDassert(!allow_sect_absorb || (aggr->size < aggr->alloc_size)); + } /* end else */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5MF_aggr_absorb() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_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 + * + *------------------------------------------------------------------------- + */ +herr_t +H5MF_aggr_query(const H5F_t *f, const H5F_blk_aggr_t *aggr, haddr_t *addr, + hsize_t *size) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_aggr_query) + + /* Check args */ + HDassert(f); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + + /* Check if this aggregator is active */ + if(f->shared->feature_flags & aggr->feature_flag) { + *addr = aggr->addr; + *size = aggr->size; + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5MF_aggr_query() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_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 +H5MF_aggr_reset(H5F_t *f, hid_t dxpl_id, H5F_blk_aggr_t *aggr) +{ + H5FD_mem_t alloc_type; /* Type of file memory to work with */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5MF_aggr_reset, FAIL) + + /* Check args */ + HDassert(f); + 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(f->shared->feature_flags & aggr->feature_flag) { + haddr_t tmp_addr; /* Temporary holder for aggregator address */ + hsize_t tmp_size; /* Temporary holder for aggregator size */ + + /* Retain aggregator info */ + tmp_addr = aggr->addr; + tmp_size = aggr->size; +#ifdef H5MF_AGGR_DBEUG +HDfprintf(stderr, "%s: tmp_addr = %a, tmp_size = %Hu\n", FUNC, tmp_addr, tmp_size); +#endif /* H5MF_AGGR_DBEUG */ + + /* Reset aggregator block information */ + aggr->tot_size = 0; + aggr->addr = 0; + aggr->size = 0; + + /* Return the unused portion of the metadata block to the file */ + if(tmp_size > 0) + if(H5FD_free(f->shared->lf, dxpl_id, alloc_type, tmp_addr, tmp_size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free space") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_aggr_reset() */ + diff --git a/src/H5MFdbg.c b/src/H5MFdbg.c new file mode 100644 index 0000000..ca83b5a --- /dev/null +++ b/src/H5MFdbg.c @@ -0,0 +1,217 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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: H5MFdbg.c + * Jan 31 2008 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: File memory management debugging functions. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5MF_PACKAGE /*suppress error about including H5MFpkg */ +#define H5MF_DEBUGGING /* Need access to file space debugging routines */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5MFpkg.h" /* File memory management */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + +/* User data for free space section iterator callback */ +typedef struct { + H5FS_t *fspace; /* Free space manager */ + FILE *stream; /* Stream for output */ + int indent; /* Indention amount */ + int fwidth; /* Field width amount */ +} H5MF_debug_iter_ud_t; + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sects_debug_cb + * + * Purpose: Prints debugging info about a free space section for a file + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * January 31 2008 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5MF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata) +{ + const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* Section to dump info */ + H5MF_debug_iter_ud_t *udata = (H5MF_debug_iter_ud_t *)_udata; /* User data for callbacks */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5MF_sects_debug_cb) + + /* + * Check arguments. + */ + HDassert(sect); + HDassert(udata); + + /* Print generic section information */ + HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth, + "Section type:", + (sect->sect_info.type == H5MF_FSPACE_SECT_SIMPLE ? "simple" : "unknown")); + HDfprintf(udata->stream, "%*s%-*s %a\n", udata->indent, "", udata->fwidth, + "Section address:", + sect->sect_info.addr); + HDfprintf(udata->stream, "%*s%-*s %Hu\n", udata->indent, "", udata->fwidth, + "Section size:", + sect->sect_info.size); + HDfprintf(udata->stream, "%*s%-*s %Hu\n", udata->indent, "", udata->fwidth, + "End of section:", + (haddr_t)((sect->sect_info.addr + sect->sect_info.size) - 1)); + HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth, + "Section state:", + (sect->sect_info.state == H5FS_SECT_LIVE ? "live" : "serialized")); + + /* Dump section-specific debugging information */ + if(H5FS_sect_debug(udata->fspace, _sect, udata->stream, udata->indent + 3, MAX(0, udata->fwidth - 3)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_BADITER, FAIL, "can't dump section's debugging info") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_sects_debug_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sects_dump + * + * Purpose: Prints debugging info about free space sections for a file. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jan 31 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5MF_sects_dump(H5F_t *f, hid_t dxpl_id, FILE *stream) +{ + haddr_t eoa; /* End of allocated space in the file */ + 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" */ + H5FD_mem_t type; /* Memory type for iteration */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5MF_sects_dump, FAIL) +HDfprintf(stderr, "%s: Dumping file free space sections\n", FUNC); + + /* + * Check arguments. + */ + HDassert(f); + HDassert(stream); + + /* Retrieve the 'eoa' for the file */ + if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed") +HDfprintf(stderr, "%s: eoa = %a\n", FUNC, eoa); + + /* Retrieve metadata aggregator info, if available */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); +HDfprintf(stderr, "%s: ma_addr = %a, ma_size = %Hu, end of ma = %a\n", FUNC, ma_addr, ma_size, (haddr_t)((ma_addr + ma_size) - 1)); + + /* Retrieve 'small data' aggregator info, if available */ + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size); +HDfprintf(stderr, "%s: sda_addr = %a, sda_size = %Hu, end of sda = %a\n", FUNC, sda_addr, sda_size, (haddr_t)((sda_addr + sda_size) - 1)); + + /* Iterate over all the free space types that have managers and dump each free list's space */ + for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) { +#ifdef QAK + /* Check if the free space for the file has been initialized */ + if(!f->shared->fs_man[type]) + if(H5MF_alloc_start(f, dxpl_id, type, FALSE) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space") +#endif /* QAK */ + + /* If there is a free space manager for this type, iterate over them */ + if(f->shared->fs_man[type]) { + H5MF_debug_iter_ud_t udata; /* User data for callbacks */ + + /* Prepare user data for section iteration callback */ + udata.fspace = f->shared->fs_man[type]; + udata.stream = stream; + udata.indent = 0; + udata.fwidth = 3; + + /* Iterate over all the free space sections */ + if(H5FS_sect_iterate(f, dxpl_id, f->shared->fs_man[type], H5MF_sects_debug_cb, &udata) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space") + } /* end if */ + } /* end for */ + +done: +HDfprintf(stderr, "%s: Done dumping file free space sections\n", FUNC); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_sects_dump() */ + diff --git a/src/H5MFpkg.h b/src/H5MFpkg.h new file mode 100644 index 0000000..0e69fd0 --- /dev/null +++ b/src/H5MFpkg.h @@ -0,0 +1,175 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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> + * Tuesday, January 8, 2008 + * + * Purpose: This file contains declarations which are visible only within + * the H5MF package. Source files outside the H5MF package should + * include H5MFprivate.h instead. + */ +#ifndef H5MF_PACKAGE +#error "Do not include this file outside the H5MF package!" +#endif + +#ifndef _H5MFpkg_H +#define _H5MFpkg_H + +/* Get package's private header */ +#include "H5MFprivate.h" + +/* Other private headers needed by this file */ +#include "H5FSprivate.h" /* File free space */ + + +/**************************/ +/* Package Private Macros */ +/**************************/ + +/* Define this to display information about file allocations */ +/* #define H5MF_ALLOC_DEBUG */ + +/* Define this to display more information about file allocations */ +/* #define H5MF_ALLOC_DEBUG_MORE */ + +/* Define this to display more information about block aggregator actions */ +/* #define H5MF_AGGR_DEBUG */ + +/* Define this to dump free space tracker contents after they've been modified */ +/* #define H5MF_ALLOC_DEBUG_DUMP */ + +/* Free space section types for file */ +/* (values stored in free space data structures in file) */ +#define H5MF_FSPACE_SECT_SIMPLE 0 /* Section is a range of actual bytes in file */ + + +/****************************/ +/* Package Private Typedefs */ +/****************************/ + +/* File free space section info */ +typedef struct H5MF_free_section_t { + H5FS_section_info_t sect_info; /* Free space section information (must be first in struct) */ +#ifdef NOT_YET + union { + struct { + H5HF_indirect_t *parent; /* Indirect block parent for free section's direct block */ + unsigned par_entry; /* Entry of free section's direct block in parent indirect block */ + } single; + struct { + struct H5HF_free_section_t *under; /* Pointer to indirect block underlying row section */ + unsigned row; /* Row for range of blocks */ + unsigned col; /* Column for range of blocks */ + unsigned num_entries; /* Number of entries covered */ + + /* Fields that aren't stored */ + hbool_t checked_out; /* Flag to indicate that a row section is temporarily out of the free space manager */ + } row; + struct { + /* Holds either a pointer to an indirect block (if its "live") or + * the block offset of it's indirect block (if its "serialized") + * (This allows the indirect block that the section is within to + * be compared with other sections, whether it's serialized + * or not) + */ + union { + H5HF_indirect_t *iblock; /* Indirect block for free section */ + hsize_t iblock_off; /* Indirect block offset in "heap space" */ + } u; + unsigned row; /* Row for range of blocks */ + unsigned col; /* Column for range of blocks */ + unsigned num_entries; /* Number of entries covered */ + + /* Fields that aren't stored */ + struct H5HF_free_section_t *parent; /* Pointer to "parent" indirect section */ + unsigned par_entry; /* Entry within parent indirect section */ + hsize_t span_size; /* Size of space tracked, in "heap space" */ + unsigned iblock_entries; /* Number of entries in indirect block where section is located */ + unsigned rc; /* Reference count of outstanding row & child indirect sections */ + unsigned dir_nrows; /* Number of direct rows in section */ + struct H5HF_free_section_t **dir_rows; /* Array of pointers to outstanding row sections */ + unsigned indir_nents; /* Number of indirect entries in section */ + struct H5HF_free_section_t **indir_ents; /* Array of pointers to outstanding child indirect sections */ + } indirect; + } u; +#endif /* NOT_YET */ +} H5MF_free_section_t; + +/* Type of "container shrink" operation to perform */ +typedef enum { + H5MF_SHRINK_EOA, /* Section should shrink the EOA value */ + H5MF_SHRINK_AGGR_ABSORB_SECT, /* Section should merge into the aggregator block */ + H5MF_SHRINK_SECT_ABSORB_AGGR /* Aggregator block should merge into the section */ +} H5MF_shrink_type_t; + +/* User data for free space manager section callbacks */ +typedef struct H5MF_sect_ud_t { + /* Down */ + H5F_t *f; /* Pointer to file to operate on */ + hid_t dxpl_id; /* DXPL for VFD operations */ + H5FD_mem_t alloc_type; /* Type of memory being allocated */ + hbool_t allow_sect_absorb; /* Whether sections are allowed to absorb a block aggregator */ + + /* Up */ + H5MF_shrink_type_t shrink; /* Type of shrink operation to perform */ + H5F_blk_aggr_t *aggr; /* Aggregator block to operate on */ +} H5MF_sect_ud_t; + + +/*****************************/ +/* Package Private Variables */ +/*****************************/ + +/* H5MF single section inherits serializable properties from H5FS_section_class_t */ +H5_DLLVAR H5FS_section_class_t H5MF_FSPACE_SECT_CLS_SIMPLE[1]; + + +/******************************/ +/* Package Private Prototypes */ +/******************************/ + +/* Allocator routines */ +H5_DLL herr_t H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, + hbool_t may_create); +H5_DLL herr_t H5MF_sects_dump(H5F_t *f, hid_t dxpl_id, FILE *stream); + +/* 'simple' section routines */ +H5_DLL H5MF_free_section_t *H5MF_sect_simple_new(haddr_t sect_off, + hsize_t sect_size); +H5_DLL htri_t H5MF_sect_simple_can_shrink(const H5FS_section_info_t *_sect, + void *udata); +H5_DLL herr_t H5MF_sect_simple_shrink(H5FS_section_info_t **_sect, + void *udata); +H5_DLL herr_t H5MF_sect_simple_free(H5FS_section_info_t *sect); + +/* Block aggregator routines */ +H5_DLL haddr_t H5MF_aggr_alloc(H5F_t *f, hid_t dxpl_id, H5F_blk_aggr_t *aggr, + H5F_blk_aggr_t *other_aggr, H5FD_mem_t type, hsize_t size); +H5_DLL htri_t H5MF_aggr_try_extend(const H5F_t *f, H5F_blk_aggr_t *aggr, + H5FD_mem_t type, haddr_t abs_blk_end, hsize_t extra_requested); +H5_DLL htri_t H5MF_aggr_can_absorb(const H5F_t *f, const H5F_blk_aggr_t *aggr, + const H5MF_free_section_t *sect, H5MF_shrink_type_t *shrink); +H5_DLL herr_t H5MF_aggr_absorb(const H5F_t *f, H5F_blk_aggr_t *aggr, + H5MF_free_section_t *sect, hbool_t allow_sect_absorb); +H5_DLL herr_t H5MF_aggr_query(const H5F_t *f, const H5F_blk_aggr_t *aggr, + haddr_t *addr, hsize_t *size); + +/* Testing routines */ +#ifdef H5MF_TESTING +#endif /* H5MF_TESTING */ + +#endif /* _H5MFpkg_H */ + diff --git a/src/H5MFprivate.h b/src/H5MFprivate.h index b2e0126..0d1da8a 100644 --- a/src/H5MFprivate.h +++ b/src/H5MFprivate.h @@ -32,6 +32,10 @@ #include "H5Fprivate.h" /* File access */ #include "H5FDprivate.h" /* File Drivers */ +/**************************/ +/* Library Private Macros */ +/**************************/ + /* * Feature: Define H5MF_DEBUG on the compiler command line if you want to * see diagnostics from this layer. @@ -40,18 +44,44 @@ # undef H5MF_DEBUG #endif -/* - * Library prototypes... - */ +/****************************/ +/* Library Private Typedefs */ +/****************************/ + + +/*****************************/ +/* Library-private Variables */ +/*****************************/ + + +/***************************************/ +/* Library-private Function Prototypes */ +/***************************************/ + +/* File space manager routines */ +H5_DLL herr_t H5MF_init_merge_flags(H5F_t *f); +H5_DLL hssize_t H5MF_get_freespace(H5F_t *f, hid_t dxpl_id); +H5_DLL herr_t H5MF_close(H5F_t *f, hid_t dxpl_id); + +/* File space allocation routines */ H5_DLL haddr_t H5MF_alloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); H5_DLL herr_t H5MF_xfree(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, 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 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); +H5_DLL herr_t H5MF_try_extend(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, + haddr_t addr, hsize_t size, hsize_t extra_requested); +H5_DLL htri_t H5MF_try_shrink(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, + haddr_t addr, hsize_t size); + +/* 'block aggregator' routines */ +H5_DLL herr_t H5MF_aggr_reset(H5F_t *file, hid_t dxpl_id, H5F_blk_aggr_t *aggr); + +/* Debugging routines */ +#ifdef H5MF_DEBUGGING +#ifdef NOT_YET +H5_DLL herr_t H5MF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, + FILE *stream, int indent, int fwidth); +#endif /* NOT_YET */ +#endif /* H5MF_DEBUGGING */ #endif /* end _H5MFprivate_H */ diff --git a/src/H5MFsection.c b/src/H5MFsection.c new file mode 100644 index 0000000..b01590e --- /dev/null +++ b/src/H5MFsection.c @@ -0,0 +1,526 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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> + * Tuesday, January 8, 2008 + * + * Purpose: Free space section callbacks for file. + * + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5MF_PACKAGE /*suppress error about including H5MFpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5MFpkg.h" /* File memory management */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* 'simple' section callbacks */ +static H5FS_section_info_t *H5MF_sect_simple_deserialize(const H5FS_section_class_t *cls, + hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + unsigned *des_flags); +static htri_t H5MF_sect_simple_can_merge(const H5FS_section_info_t *sect1, + const H5FS_section_info_t *sect2, void *udata); +static herr_t H5MF_sect_simple_merge(H5FS_section_info_t *sect1, + H5FS_section_info_t *sect2, void *udata); +static herr_t H5MF_sect_simple_valid(const H5FS_section_class_t *cls, + const H5FS_section_info_t *sect); +static H5FS_section_info_t *H5MF_sect_simple_split(H5FS_section_info_t *sect, + hsize_t frag_size); + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Class info for "simple" free space sections */ +H5FS_section_class_t H5MF_FSPACE_SECT_CLS_SIMPLE[1] = {{ + /* Class variables */ + H5MF_FSPACE_SECT_SIMPLE, /* Section type */ + 0, /* Extra serialized size */ + H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ + NULL, /* Initialize section class */ + NULL, /* Terminate section class */ + + /* Object methods */ + NULL, /* Add section */ + NULL, /* Serialize section */ + H5MF_sect_simple_deserialize, /* Deserialize section */ + H5MF_sect_simple_can_merge, /* Can sections merge? */ + H5MF_sect_simple_merge, /* Merge sections */ + H5MF_sect_simple_can_shrink, /* Can section shrink container?*/ + H5MF_sect_simple_shrink, /* Shrink container w/section */ + H5MF_sect_simple_free, /* Free section */ + H5MF_sect_simple_valid, /* Check validity of section */ + H5MF_sect_simple_split, /* Split section node for alignment */ + NULL, /* Dump debugging for section */ +}}; + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage the H5MF_free_section_t struct */ +H5FL_DEFINE(H5MF_free_section_t); + + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_simple_new + * + * Purpose: Create a new 'simple' section and return it to the caller + * + * Return: Pointer to new section on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * January 8 2008 + * + *------------------------------------------------------------------------- + */ +H5MF_free_section_t * +H5MF_sect_simple_new(haddr_t sect_off, hsize_t sect_size) +{ + H5MF_free_section_t *sect = NULL; /* 'Simple' free space section to add */ + H5MF_free_section_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_new) + + /* Check arguments. */ + HDassert(sect_size); + + /* Create free space section node */ + if(NULL == (sect = H5FL_MALLOC(H5MF_free_section_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct block free list section") + + /* Set the information passed in */ + sect->sect_info.addr = sect_off; + sect->sect_info.size = sect_size; + + /* Set the section's class & state */ + sect->sect_info.type = H5MF_FSPACE_SECT_SIMPLE; + sect->sect_info.state = H5FS_SECT_LIVE; + + /* Set return value */ + ret_value = sect; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_sect_simple_new() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_simple_deserialize + * + * Purpose: Deserialize a buffer into a "live" single section + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, January 8, 2008 + * + *------------------------------------------------------------------------- + */ +static H5FS_section_info_t * +H5MF_sect_simple_deserialize(const H5FS_section_class_t UNUSED *cls, + hid_t UNUSED dxpl_id, const uint8_t UNUSED *buf, haddr_t sect_addr, + hsize_t sect_size, unsigned UNUSED *des_flags) +{ + H5MF_free_section_t *sect; /* New section */ + H5FS_section_info_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_deserialize) + + /* Check arguments. */ + HDassert(H5F_addr_defined(sect_addr)); + HDassert(sect_size); + + /* Create free space section for block */ + if(NULL == (sect = H5MF_sect_simple_new(sect_addr, sect_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't initialize free space section") + + /* Set return value */ + ret_value = (H5FS_section_info_t *)sect; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_simple_deserialize() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_simple_can_merge + * + * Purpose: Can two sections of this type merge? + * + * Note: Second section must be "after" first section + * + * Return: Success: non-negative (TRUE/FALSE) + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, January 8, 2008 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5MF_sect_simple_can_merge(const H5FS_section_info_t *_sect1, + const H5FS_section_info_t *_sect2, void UNUSED *_udata) +{ + const H5MF_free_section_t *sect1 = (const H5MF_free_section_t *)_sect1; /* File free section */ + const H5MF_free_section_t *sect2 = (const H5MF_free_section_t *)_sect2; /* File free section */ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_sect_simple_can_merge) + + /* Check arguments. */ + HDassert(sect1); + HDassert(sect2); + HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */ + HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); + + /* Check if second section adjoins first section */ + ret_value = H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_simple_can_merge() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_simple_merge + * + * Purpose: Merge two sections of this type + * + * Note: Second section always merges into first node + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, January 8, 2008 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5MF_sect_simple_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, + void UNUSED *_udata) +{ + H5MF_free_section_t *sect1 = (H5MF_free_section_t *)_sect1; /* File free section */ + H5MF_free_section_t *sect2 = (H5MF_free_section_t *)_sect2; /* File free section */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_merge) + + /* Check arguments. */ + HDassert(sect1); + HDassert(sect1->sect_info.type == H5MF_FSPACE_SECT_SIMPLE); + HDassert(sect2); + HDassert(sect2->sect_info.type == H5MF_FSPACE_SECT_SIMPLE); + HDassert(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr)); + + /* Add second section's size to first section */ + sect1->sect_info.size += sect2->sect_info.size; + + /* Get rid of second section */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)sect2) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_simple_merge() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_simple_can_shrink + * + * Purpose: Can this section shrink the container? + * + * Return: Success: non-negative (TRUE/FALSE) + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, January 8, 2008 + * + *------------------------------------------------------------------------- + */ +htri_t +H5MF_sect_simple_can_shrink(const H5FS_section_info_t *_sect, void *_udata) +{ + const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */ + H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ + haddr_t eoa; /* End of address space in the file */ + haddr_t end; /* End of section to extend */ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_can_shrink) + + /* Check arguments. */ + HDassert(sect); + HDassert(udata); + HDassert(udata->f); + + /* Retrieve the end of the file's address space */ + if(HADDR_UNDEF == (eoa = H5FD_get_eoa(udata->f->shared->lf, H5FD_MEM_DEFAULT))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed") + + /* Compute address of end of section to check */ + end = sect->sect_info.addr + sect->sect_info.size; + + /* Check if the section is exactly at the end of the allocated space in the file */ + if(H5F_addr_eq(end, eoa)) { + /* Set the shrinking type */ + udata->shrink = H5MF_SHRINK_EOA; +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: section {%a, %Hu}, shrinks file, eoa = %a\n", FUNC, sect->sect_info.addr, sect->sect_info.size, eoa); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* Indicate shrinking can occur */ + HGOTO_DONE(TRUE) + } /* end if */ + else { + /* Check if this section is allowed to merge with metadata aggregation block */ + if(udata->f->shared->fs_aggr_merge[udata->alloc_type] & H5F_FS_MERGE_METADATA) { + htri_t status; /* Status from aggregator adjoin */ + + /* See if section can absorb the aggregator & vice versa */ + if((status = H5MF_aggr_can_absorb(udata->f, &(udata->f->shared->meta_aggr), sect, &(udata->shrink))) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "error merging section with aggregation block") + else if(status > 0) { + /* Set the aggregator to operate on */ + udata->aggr = &(udata->f->shared->meta_aggr); +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: section {%a, %Hu}, adjoins metadata aggregator\n", FUNC, sect->sect_info.addr, sect->sect_info.size); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* Indicate shrinking can occur */ + HGOTO_DONE(TRUE) + } /* end if */ + } /* end if */ + + /* Check if this section is allowed to merge with small 'raw' aggregation block */ + if(udata->f->shared->fs_aggr_merge[udata->alloc_type] & H5F_FS_MERGE_RAWDATA) { + htri_t status; /* Status from aggregator adjoin */ + + /* See if section can absorb the aggregator & vice versa */ + if((status = H5MF_aggr_can_absorb(udata->f, &(udata->f->shared->sdata_aggr), sect, &(udata->shrink))) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "error merging section with aggregation block") + else if(status > 0) { + /* Set the aggregator to operate on */ + udata->aggr = &(udata->f->shared->sdata_aggr); +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: section {%a, %Hu}, adjoins small data aggregator\n", FUNC, sect->sect_info.addr, sect->sect_info.size); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* Indicate shrinking can occur */ + HGOTO_DONE(TRUE) + } /* end if */ + } /* end if */ + } /* end else */ + + /* Set return value */ + ret_value = FALSE; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_simple_can_shrink() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_simple_shrink + * + * Purpose: Shrink container with section + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, January 8, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5MF_sect_simple_shrink(H5FS_section_info_t **_sect, void *_udata) +{ + H5MF_free_section_t **sect = (H5MF_free_section_t **)_sect; /* File free section */ + H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_shrink) + + /* Check arguments. */ + HDassert(sect); + HDassert(udata); + HDassert(udata->f); + + /* Check for shrinking file */ + if(H5MF_SHRINK_EOA == udata->shrink) { + /* Release section's space at EOA with file driver */ + if(H5FD_free(udata->f->shared->lf, udata->dxpl_id, H5FD_MEM_DEFAULT, (*sect)->sect_info.addr, (*sect)->sect_info.size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "driver free request failed") + } /* end if */ + else { + /* Sanity check */ + HDassert(udata->aggr); + + /* Absorb the section into the aggregator or vice versa */ + if(H5MF_aggr_absorb(udata->f, udata->aggr, *sect, udata->allow_sect_absorb) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "can't absorb section into aggregator or vice versa") + } /* end else */ + + /* Check for freeing section */ + if(udata->shrink != H5MF_SHRINK_SECT_ABSORB_AGGR) { + /* Free section */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)*sect) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node") + + /* Mark section as freed, for free space manager */ + *sect = NULL; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_sect_simple_shrink() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_simple_free + * + * Purpose: Free a 'single' section node + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, January 8, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5MF_sect_simple_free(H5FS_section_info_t *_sect) +{ + H5MF_free_section_t *sect = (H5MF_free_section_t *)_sect; /* File free section */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_sect_simple_free) + + /* Check arguments. */ + HDassert(sect); + + /* Release the section */ + H5FL_FREE(H5MF_free_section_t, sect); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5MF_sect_simple_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_simple_valid + * + * Purpose: Check the validity of a section + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, January 8, 2008 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5MF_sect_simple_valid(const H5FS_section_class_t UNUSED *cls, + const H5FS_section_info_t *_sect) +{ + const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_sect_simple_valid) + + /* Check arguments. */ + HDassert(sect); + + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5MF_sect_simple_valid() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_sect_simple_split + * + * Purpose: Split SECT into 2 sections: fragment for alignment & the aligned section + * SECT's addr and size are updated to point to the aligned section + * + * Return: Success: the fragment for aligning sect + * Failure: null + * + * Programmer: Vailin Choi, July 29, 2008 + * + *------------------------------------------------------------------------- + */ +static H5FS_section_info_t * +H5MF_sect_simple_split(H5FS_section_info_t *sect, hsize_t frag_size) +{ + H5MF_free_section_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_split) + + /* Allocate space for new section */ + if(NULL == (ret_value = H5MF_sect_simple_new(sect->addr, frag_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't initialize free space section") + + /* Set new section's info */ + sect->addr += frag_size; + sect->size -= frag_size; + +done: + FUNC_LEAVE_NOAPI((H5FS_section_info_t *)ret_value) +} /* end H5MF_sect_simple_split() */ + + @@ -1062,9 +1062,11 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id, /* check args */ HDassert(f); + HDassert(f->intent & H5F_ACC_RDWR); HDassert(loc); HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE)); + /* Make certain we allocate at least a reasonable size for the object header */ size_hint = H5O_ALIGN_F(f, MAX(H5O_MIN_SIZE, size_hint)); @@ -1448,7 +1450,7 @@ H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file") /* Mark the object header as deleted */ - oh_flags = H5C__DELETED_FLAG; + oh_flags = H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; } /* end else */ } /* end if */ } else { @@ -1833,7 +1835,7 @@ H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file") done: - if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0) + if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") FUNC_LEAVE_NOAPI(ret_value) @@ -1879,10 +1881,6 @@ H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message") } /* end for */ - /* Free main (first) object header "chunk" */ - if(H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, oh->chunk[0].addr, (hsize_t)oh->chunk[0].size) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header") - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_delete_oh() */ diff --git a/src/H5Oalloc.c b/src/H5Oalloc.c index f9e06ad..3234d82 100644 --- a/src/H5Oalloc.c +++ b/src/H5Oalloc.c @@ -64,8 +64,8 @@ static herr_t H5O_eliminate_gap(H5O_t *oh, H5O_mesg_t *mesg, uint8_t *new_gap_loc, size_t new_gap_size); static herr_t H5O_alloc_null(H5O_t *oh, unsigned null_idx, const H5O_msg_class_t *new_type, void *new_native, size_t new_size); -static htri_t H5O_alloc_extend_chunk(H5F_t *f, H5O_t *oh, unsigned chunkno, - size_t size, unsigned * msg_idx); +static htri_t H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, + unsigned chunkno, size_t size, unsigned * msg_idx); static unsigned H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size); static htri_t H5O_move_msgs_forward(H5O_t *oh); @@ -457,6 +457,7 @@ done: */ static htri_t H5O_alloc_extend_chunk(H5F_t *f, + hid_t dxpl_id, H5O_t *oh, unsigned chunkno, size_t size, @@ -466,7 +467,7 @@ H5O_alloc_extend_chunk(H5F_t *f, size_t aligned_size = H5O_ALIGN_OH(oh, size); uint8_t *old_image; /* Old address of chunk's image in memory */ size_t old_size; /* Old size of chunk */ - htri_t tri_result; /* Result from checking if chunk can be extended */ + htri_t extended; /* If chunk can be extended */ int extend_msg = -1;/* Index of null message to extend */ uint8_t new_size_flags = 0; /* New chunk #0 size flags */ hbool_t adjust_size_flags = FALSE; /* Whether to adjust the chunk #0 size flags */ @@ -534,16 +535,12 @@ H5O_alloc_extend_chunk(H5F_t *f, } /* end if */ /* Determine whether the chunk can be extended */ - tri_result = H5MF_can_extend(f, H5FD_MEM_OHDR, oh->chunk[chunkno].addr, + extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_OHDR, oh->chunk[chunkno].addr, (hsize_t)(oh->chunk[chunkno].size), (hsize_t)(delta + extra_prfx_size)); - if(tri_result == FALSE) /* can't extend -- we are done */ + if(extended < 0) /* error */ + HGOTO_ERROR(H5E_OHDR, H5E_CANTEXTEND, FAIL, "can't tell if we can extend chunk") + else if(extended == FALSE) /* can't extend -- we are done */ HGOTO_DONE(FALSE) - else if(tri_result < 0) /* error */ - HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, "can't tell if we can extend chunk") - - /* If we get this far, we should be able to extend the chunk */ - if(H5MF_extend(f, H5FD_MEM_OHDR, oh->chunk[chunkno].addr, (hsize_t)(oh->chunk[chunkno].size), (hsize_t)(delta + extra_prfx_size)) < 0 ) - HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, "can't extend chunk") /* Adjust object header prefix flags */ if(adjust_size_flags) { @@ -994,13 +991,13 @@ H5O_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type, HDassert(H5F_addr_defined(oh->chunk[chunkno].addr)); - tri_result = H5O_alloc_extend_chunk(f, oh, chunkno, raw_size, &idx); + tri_result = H5O_alloc_extend_chunk(f, dxpl_id, oh, chunkno, raw_size, &idx); if(tri_result == TRUE) break; else if(tri_result == FALSE) idx = UFAIL; else - HGOTO_ERROR(H5E_OHDR, H5E_SYSTEM, UFAIL, "H5O_alloc_extend_chunk failed unexpectedly") + HGOTO_ERROR(H5E_OHDR, H5E_CANTEXTEND, UFAIL, "H5O_alloc_extend_chunk failed unexpectedly") } /* end for */ /* If idx is still UFAIL, we were not able to extend a chunk, diff --git a/src/H5Ocache.c b/src/H5Ocache.c index 35b4e07..c50f557 100644 --- a/src/H5Ocache.c +++ b/src/H5Ocache.c @@ -37,6 +37,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free lists */ +#include "H5MFprivate.h" /* File memory management */ #include "H5Opkg.h" /* Object headers */ @@ -130,8 +131,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, unsigned merged_null_msgs = 0; /* Number of null messages merged together */ haddr_t chunk_addr; /* Address of first chunk */ size_t chunk_size; /* Size of first chunk */ - haddr_t abs_eoa; /* Absolute end of file address */ - haddr_t rel_eoa; /* Relative end of file address */ + haddr_t eoa; /* Relative end of file address */ H5O_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5O_load, NULL) @@ -143,14 +143,11 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, HDassert(!_udata2); /* Make certain we don't speculatively read off the end of the file */ - if(HADDR_UNDEF == (abs_eoa = H5F_get_eoa(f))) + if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_OHDR))) HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine file size") - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa = abs_eoa - H5F_get_base_addr(f); - /* Compute the size of the speculative object header buffer */ - H5_ASSIGN_OVERFLOW(spec_read_size, MIN(rel_eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t); + H5_ASSIGN_OVERFLOW(spec_read_size, MIN(eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t); /* Attempt to speculatively read both object header prefix and first chunk */ if(H5F_block_read(f, H5FD_MEM_OHDR, addr, spec_read_size, dxpl_id, read_buf) < 0) @@ -415,7 +412,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, #endif /* NDEBUG */ /* Check for combining two adjacent 'null' messages */ - if((H5F_get_intent(f) & H5F_ACC_RDWR) && + if((H5F_INTENT(f) & H5F_ACC_RDWR) && H5O_NULL_ID == id && oh->nmesgs > 0 && H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id && oh->mesg[oh->nmesgs - 1].chunkno == chunkno) { @@ -468,7 +465,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, /* Check for "mark if unknown" message flag, etc. */ else if((flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN) && !(flags & H5O_MSG_FLAG_WAS_UNKNOWN) && - (H5F_get_intent(f) & H5F_ACC_RDWR)) { + (H5F_INTENT(f) & H5F_ACC_RDWR)) { /* Mark the message as "unknown" */ /* This is a bit aggressive, since the application may @@ -838,20 +835,37 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_dest(H5F_t UNUSED *f, H5O_t *oh) +H5O_dest(H5F_t *f, H5O_t *oh) { unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_dest) + FUNC_ENTER_NOAPI_NOINIT(H5O_dest) +#ifdef QAK +HDfprintf(stderr, "%s: oh->cache_info.addr = %a\n", FUNC, oh->cache_info.addr); +HDfprintf(stderr, "%s: oh->cache_info.free_file_space_on_destroy = %t\n", FUNC, oh->cache_info.free_file_space_on_destroy); +#endif /* QAK */ /* check args */ HDassert(oh); /* Verify that node is clean */ - HDassert(oh->cache_info.is_dirty == FALSE); + HDassert(!oh->cache_info.is_dirty); + + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!oh->cache_info.free_file_space_on_destroy || H5F_addr_defined(oh->cache_info.addr)); /* destroy chunks */ if(oh->chunk) { + /* Check for releasing file space for object header */ + if(oh->cache_info.free_file_space_on_destroy) { + /* Free main (first) object header "chunk" */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_dxpl_id, oh->chunk[0].addr, (hsize_t)oh->chunk[0].size) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header") + } /* end if */ + + /* Release buffer for each chunk */ for(u = 0; u < oh->nchunks; u++) { /* Verify that chunk is clean */ HDassert(oh->chunk[u].dirty == 0); @@ -859,6 +873,7 @@ H5O_dest(H5F_t UNUSED *f, H5O_t *oh) oh->chunk[u].image = H5FL_BLK_FREE(chunk_image, oh->chunk[u].image); } /* end for */ + /* Release array of chunk info */ oh->chunk = (H5O_chunk_t *)H5FL_SEQ_FREE(H5O_chunk_t, oh->chunk); } /* end if */ @@ -877,7 +892,8 @@ H5O_dest(H5F_t UNUSED *f, H5O_t *oh) /* destroy object header */ (void)H5FL_FREE(H5O_t, oh); - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_dest() */ diff --git a/src/H5Omessage.c b/src/H5Omessage.c index bfe40f8..1682117 100644 --- a/src/H5Omessage.c +++ b/src/H5Omessage.c @@ -879,7 +879,7 @@ H5O_msg_count_real(const H5O_t *oh, const H5O_msg_class_t *type) *------------------------------------------------------------------------- */ htri_t -H5O_msg_exists(H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id) +H5O_msg_exists(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id) { H5O_t *oh = NULL; /* Object header for location */ htri_t ret_value; /* Return value */ diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 09b9b02..f65b15d 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -580,7 +580,7 @@ H5_DLL herr_t H5O_msg_reset(unsigned type_id, void *native); H5_DLL void *H5O_msg_free(unsigned type_id, void *mesg); H5_DLL void *H5O_msg_copy(unsigned type_id, const void *mesg, void *dst); H5_DLL int H5O_msg_count(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id); -H5_DLL htri_t H5O_msg_exists(H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id); +H5_DLL htri_t H5O_msg_exists(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id); H5_DLL herr_t H5O_msg_remove(const H5O_loc_t *loc, unsigned type_id, int sequence, hbool_t adj_link, hid_t dxpl_id); H5_DLL herr_t H5O_msg_remove_op(const H5O_loc_t *loc, unsigned type_id, int sequence, @@ -1290,6 +1290,187 @@ done: /*-------------------------------------------------------------------------- NAME + H5SL_below + PURPOSE + Search for _node_ in a skip list whose object is less than or equal to 'key' + USAGE + H5SL_node_t *H5SL_below(slist, key) + H5SL_t *slist; IN/OUT: Pointer to skip list + void *key; IN: Key for item to search for + + RETURNS + Returns pointer to _node_ who key is less than or equal to 'key' on success, + NULL on failure + DESCRIPTION + Search for a node with an object in a skip list, according to it's key, + returning the node itself (for an exact match), or the node with the next + highest key that is less than 'key' + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5SL_node_t * +H5SL_below(H5SL_t *slist, const void *key) +{ + H5SL_node_t *x; /* Current node to examine */ + uint32_t hashval = 0; /* Hash value for key */ + H5SL_node_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_below) + + /* Check args */ + HDassert(slist); + HDassert(key); + + /* Check internal consistency */ + /* (Pre-condition) */ + + /* Insert item into skip list */ + + /* Work through the forward pointers for a node, finding the node at each + * level that is before the location to insert + */ + x = slist->header; + switch(slist->type) { + case H5SL_TYPE_INT: + H5SL_FIND(SCALAR, slist, x, -, const int, key, -) + break; + + case H5SL_TYPE_HADDR: + H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -) + break; + + case H5SL_TYPE_STR: + H5SL_FIND(STRING, slist, x, -, char *, key, hashval) + break; + + case H5SL_TYPE_HSIZE: + H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -) + break; + + case H5SL_TYPE_UNSIGNED: + H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -) + break; + + case H5SL_TYPE_SIZE: + 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 */ + + /* An exact match for 'key' must not have been found in list, if we get here */ + /* Check for a node with a key that is less than the given 'key' */ + if(NULL == x) { + /* Check for walking off the list */ + if(slist->last != slist->header) + ret_value = slist->last; + else + ret_value = NULL; + } /* end if */ + else { + if(x->backward != slist->header) + ret_value = x->backward; + else + ret_value = NULL; + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SL_below() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_above + PURPOSE + Search for _node_ in a skip list whose object is greater than or equal to 'key' + USAGE + H5SL_node_t *H5SL_above(slist, key) + H5SL_t *slist; IN/OUT: Pointer to skip list + void *key; IN: Key for item to search for + + RETURNS + Returns pointer to _node_ with object that has a key is greater than or + equal to 'key' on success, NULL on failure + DESCRIPTION + Search for a node with an object in a skip list, according to it's key, + returning the node itself (for an exact match), or the node with the next + lowest key that is greater than 'key' + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5SL_node_t * +H5SL_above(H5SL_t *slist, const void *key) +{ + H5SL_node_t *x; /* Current node to examine */ + uint32_t hashval = 0; /* Hash value for key */ + H5SL_node_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_above) + + /* Check args */ + HDassert(slist); + HDassert(key); + + /* Check internal consistency */ + /* (Pre-condition) */ + + /* Insert item into skip list */ + + /* Work through the forward pointers for a node, finding the node at each + * level that is before the location to insert + */ + x = slist->header; + switch(slist->type) { + case H5SL_TYPE_INT: + H5SL_FIND(SCALAR, slist, x, -, const int, key, -) + break; + + case H5SL_TYPE_HADDR: + H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -) + break; + + case H5SL_TYPE_STR: + H5SL_FIND(STRING, slist, x, -, char *, key, hashval) + break; + + case H5SL_TYPE_HSIZE: + H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -) + break; + + case H5SL_TYPE_UNSIGNED: + H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -) + break; + + case H5SL_TYPE_SIZE: + 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 */ + + /* An exact match for 'key' must not have been found in list, if we get here */ + /* ('x' must be the next node with a key greater than the 'key', or NULL) */ + if(x) + ret_value = x; + else + ret_value = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SL_above() */ + + +/*-------------------------------------------------------------------------- + NAME H5SL_first PURPOSE Gets a pointer to the first node in a skip list diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h index 9f73893..27bb4d1 100644 --- a/src/H5SLprivate.h +++ b/src/H5SLprivate.h @@ -72,6 +72,8 @@ H5_DLL void *H5SL_search(H5SL_t *slist, const void *key); H5_DLL void *H5SL_less(H5SL_t *slist, const void *key); H5_DLL void *H5SL_greater(H5SL_t *slist, const void *key); H5_DLL H5SL_node_t *H5SL_find(H5SL_t *slist, const void *key); +H5_DLL H5SL_node_t *H5SL_below(H5SL_t *slist, const void *key); +H5_DLL H5SL_node_t *H5SL_above(H5SL_t *slist, const void *key); H5_DLL H5SL_node_t *H5SL_first(H5SL_t *slist); H5_DLL H5SL_node_t *H5SL_next(H5SL_node_t *slist_node); H5_DLL H5SL_node_t *H5SL_prev(H5SL_node_t *slist_node); @@ -529,23 +529,31 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5SM_delete_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id, hbool_t delete_heap) +H5SM_delete_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id, + hbool_t delete_heap) { - hsize_t list_size; /* Size of list on disk */ - herr_t ret_value = SUCCEED; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5SM_delete_index) /* Determine whether index is a list or a B-tree. */ if(header->index_type == H5SM_LIST) { - /* Eject entry from cache */ - if(H5AC_expunge_entry(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove list index from cache") - - /* Free the file space used */ - list_size = H5SM_LIST_SIZE(f, header->list_max); - if(H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, dxpl_id, header->index_addr, list_size) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to free shared message list") + unsigned index_status = 0; /* Index list's status in the metadata cache */ + + /* Check the index list's status in the metadata cache */ + if(H5AC_get_entry_status(f, header->index_addr, &index_status) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to check metadata cache status for direct block") + + /* If the index list is in the cache, expunge it now */ + if(index_status & H5AC_ES__IN_CACHE) { + /* Sanity checks on index list */ + HDassert(!(index_status & H5AC_ES__IS_PINNED)); + HDassert(!(index_status & H5AC_ES__IS_PROTECTED)); + + /* Evict the index list from the metadata cache */ + if(H5AC_expunge_entry(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove list index from cache") + } /* end if */ } /* end if */ else { HDassert(header->index_type == H5SM_BTREE); @@ -727,7 +735,7 @@ H5SM_convert_list_to_btree(H5F_t *f, H5SM_index_header_t *header, } /* end for */ /* Unprotect list in cache and release heap */ - if(H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG) < 0) + if(H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to release SOHM list") *_list = list = NULL; @@ -1691,7 +1699,7 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, if(header->num_messages == 0) { /* Unprotect cache and release heap */ - if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG) < 0) + if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to release SOHM list") list = NULL; @@ -2064,11 +2072,15 @@ H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id, message = list->messages[list_pos]; } /* end if */ else { + htri_t msg_exists; /* Whether the message exists in the v2 B-tree */ + /* Index is a B-tree */ HDassert(header->index_type == H5SM_BTREE); /* Look up the message in the v2 B-tree */ - if(H5B2_find(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, H5SM_get_refcount_bt2_cb, &message) < 0) + if((msg_exists = H5B2_find(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, H5SM_get_refcount_bt2_cb, &message)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "error finding message in index") + if(!msg_exists) HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "message not in index") } /* end else */ diff --git a/src/H5SMcache.c b/src/H5SMcache.c index 021b43f..91478c5 100644 --- a/src/H5SMcache.c +++ b/src/H5SMcache.c @@ -27,6 +27,7 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ #include "H5FLprivate.h" /* Free Lists */ +#include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ #include "H5SMpkg.h" /* Shared object header messages */ #include "H5WBprivate.h" /* Wrapped Buffers */ @@ -652,18 +653,34 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5SM_list_dest(H5F_t UNUSED *f, H5SM_list_t* list) +H5SM_list_dest(H5F_t *f, H5SM_list_t* list) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_list_dest) + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5SM_list_dest) + /* Sanity check */ HDassert(list); + HDassert(list->header); HDassert(list->messages); - H5FL_ARR_FREE(H5SM_sohm_t, list->messages); + /* If we're going to free the space on disk, the address must be valid */ + HDassert(!list->cache_info.free_file_space_on_destroy || H5F_addr_defined(list->cache_info.addr)); + + /* Check for freeing file space for shared message index list */ + if(list->cache_info.free_file_space_on_destroy) { + /* Release the space on disk */ + /* (XXX: Nasty usage of internal DXPL value! -QAK) */ + if(H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, H5AC_dxpl_id, list->cache_info.addr, (hsize_t)H5SM_LIST_SIZE(f, list->header->list_max)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "unable to free shared message list") + } /* end if */ + /* Release resources */ + H5FL_ARR_FREE(H5SM_sohm_t, list->messages); (void)H5FL_FREE(H5SM_list_t, list); - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5SM_list_dest() */ diff --git a/src/H5Spoint.c b/src/H5Spoint.c index a93e274..74d72d9 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -878,8 +878,8 @@ H5S_point_deserialize (H5S_t *space, const uint8_t *buf) UINT32DECODE(buf, *tcoord); /* Select points */ - if(H5S_select_elements(space,op,num_elem,(const hsize_t *)coord) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection"); + if(H5S_select_elements(space, op, num_elem, (const hsize_t *)coord) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") done: /* Free the coordinate array if necessary */ diff --git a/src/Makefile.am b/src/Makefile.am index fcb47e2..a73e383 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,20 +51,25 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Dio.c \ H5Distore.c H5Dmpio.c H5Doh.c H5Dscatgath.c H5Dselect.c H5Dtest.c \ H5E.c H5Edeprec.c H5Eint.c \ - H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \ + H5F.c H5Faccum.c H5Fdbg.c H5Ffake.c H5Fio.c H5Fmount.c H5Fmpi.c H5Fquery.c \ + H5Fsfile.c H5Fsuper.c H5Ftest.c \ H5FD.c H5FDcore.c \ - H5FDdirect.c H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ + H5FDdirect.c H5FDfamily.c H5FDint.c H5FDlog.c H5FDmpi.c H5FDmpio.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 \ + H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c H5FSstat.c H5FStest.c \ + H5G.c H5Gbtree2.c H5Gcache.c \ + H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \ H5Gint.c H5Glink.c \ H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c H5Goh.c H5Gstab.c H5Gtest.c \ H5Gtraverse.c \ H5HF.c H5HFbtree2.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \ H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \ H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \ - H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5L.c H5Lexternal.c \ - H5MF.c H5MM.c H5MP.c H5MPtest.c \ + H5HG.c H5HGcache.c H5HGdbg.c \ + H5HL.c H5HLcache.c H5HLdbg.c \ + H5HP.c H5I.c H5L.c H5Lexternal.c \ + H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \ + H5MM.c H5MP.c H5MPtest.c \ H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \ H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c \ H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 878380b..7a4bd25 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -86,40 +86,43 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5Dcontig.lo H5Ddbg.lo H5Ddeprec.lo H5Defl.lo H5Dfill.lo \ H5Dint.lo H5Dio.lo H5Distore.lo H5Dmpio.lo H5Doh.lo \ H5Dscatgath.lo H5Dselect.lo H5Dtest.lo H5E.lo H5Edeprec.lo \ - H5Eint.lo H5F.lo H5Fdbg.lo H5Ffake.lo H5Fmount.lo H5Fsfile.lo \ - H5Fsuper.lo H5Ftest.lo H5FD.lo H5FDcore.lo H5FDdirect.lo \ - H5FDfamily.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \ - H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo \ - H5FDstdio.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo \ - H5FSsection.lo H5G.lo H5Gbtree2.lo H5Gcompact.lo H5Gdense.lo \ - H5Gdeprec.lo H5Gent.lo H5Gint.lo H5Glink.lo H5Gloc.lo \ - H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo H5Gstab.lo H5Gtest.lo \ - H5Gtraverse.lo H5HF.lo H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo \ - H5HFdblock.lo H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo \ - H5HFiblock.lo H5HFiter.lo H5HFman.lo H5HFsection.lo \ - H5HFspace.lo H5HFstat.lo H5HFtest.lo H5HFtiny.lo H5HG.lo \ - H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo H5I.lo H5L.lo \ - 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 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 + H5Eint.lo H5F.lo H5Faccum.lo H5Fdbg.lo H5Ffake.lo H5Fio.lo \ + H5Fmount.lo H5Fmpi.lo H5Fquery.lo H5Fsfile.lo H5Fsuper.lo \ + H5Ftest.lo H5FD.lo H5FDcore.lo H5FDdirect.lo H5FDfamily.lo \ + H5FDint.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo H5FDmpiposix.lo \ + H5FDmulti.lo H5FDsec2.lo H5FDspace.lo H5FDstdio.lo H5FL.lo \ + H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo H5FSsection.lo \ + H5FSstat.lo H5FStest.lo H5G.lo H5Gbtree2.lo H5Gcache.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 H5HGcache.lo H5HGdbg.lo H5HL.lo \ + H5HLcache.lo H5HLdbg.lo H5HP.lo H5I.lo H5L.lo H5Lexternal.lo \ + H5MF.lo H5MFaggr.lo H5MFdbg.lo H5MFsection.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 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) \ @@ -429,20 +432,25 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Dio.c \ H5Distore.c H5Dmpio.c H5Doh.c H5Dscatgath.c H5Dselect.c H5Dtest.c \ H5E.c H5Edeprec.c H5Eint.c \ - H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \ + H5F.c H5Faccum.c H5Fdbg.c H5Ffake.c H5Fio.c H5Fmount.c H5Fmpi.c H5Fquery.c \ + H5Fsfile.c H5Fsuper.c H5Ftest.c \ H5FD.c H5FDcore.c \ - H5FDdirect.c H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ + H5FDdirect.c H5FDfamily.c H5FDint.c H5FDlog.c H5FDmpi.c H5FDmpio.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 \ + H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c H5FSstat.c H5FStest.c \ + H5G.c H5Gbtree2.c H5Gcache.c \ + H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \ H5Gint.c H5Glink.c \ H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c H5Goh.c H5Gstab.c H5Gtest.c \ H5Gtraverse.c \ H5HF.c H5HFbtree2.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \ H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \ H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \ - H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5L.c H5Lexternal.c \ - H5MF.c H5MM.c H5MP.c H5MPtest.c \ + H5HG.c H5HGcache.c H5HGdbg.c \ + H5HL.c H5HLcache.c H5HLdbg.c \ + H5HP.c H5I.c H5L.c H5Lexternal.c \ + H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \ + H5MM.c H5MP.c H5MPtest.c \ H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \ H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c \ H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \ @@ -645,6 +653,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDcore.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDdirect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDfamily.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDlog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmpi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmpio.Plo@am__quote@ @@ -659,14 +668,21 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FScache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FSdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FSsection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FSstat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FStest.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Faccum.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ffake.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmount.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmpi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fquery.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsfile.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsuper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ftest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5G.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gbtree2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gcompact.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gdense.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gdeprec.Plo@am__quote@ @@ -698,14 +714,19 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtiny.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HG.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HGcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HGdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HL.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HP.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5I.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5L.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Lexternal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MF.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MFaggr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MFdbg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MFsection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MM.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MP.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MPtest.Plo@am__quote@ diff --git a/test/Makefile.am b/test/Makefile.am index 04c480a..aa5ceb6 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -42,7 +42,7 @@ TEST_PROG=testhdf5 lheap ohdr stab gheap cache cache_api \ fillval mount flush1 flush2 app_ref enum \ set_extent ttsafe \ getname vfd ntypes dangle dtransform reserved cross_read \ - btree2 fheap + freespace mf btree2 fheap # List programs to be built when testing here. error_test and err_compat are # built at the same time as the other tests, but executed by testerror.sh. diff --git a/test/Makefile.in b/test/Makefile.in index 79fbc7d..4f3122b 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -80,7 +80,8 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \ app_ref$(EXEEXT) enum$(EXEEXT) set_extent$(EXEEXT) \ ttsafe$(EXEEXT) getname$(EXEEXT) vfd$(EXEEXT) ntypes$(EXEEXT) \ dangle$(EXEEXT) dtransform$(EXEEXT) reserved$(EXEEXT) \ - cross_read$(EXEEXT) btree2$(EXEEXT) fheap$(EXEEXT) + cross_read$(EXEEXT) freespace$(EXEEXT) mf$(EXEEXT) \ + btree2$(EXEEXT) fheap$(EXEEXT) am__EXEEXT_2 = gen_bad_ohdr$(EXEEXT) gen_bogus$(EXEEXT) \ gen_cross$(EXEEXT) gen_deflate$(EXEEXT) gen_filters$(EXEEXT) \ gen_new_array$(EXEEXT) gen_new_fill$(EXEEXT) \ @@ -177,6 +178,10 @@ flush2_SOURCES = flush2.c flush2_OBJECTS = flush2.$(OBJEXT) flush2_LDADD = $(LDADD) flush2_DEPENDENCIES = libh5test.la $(LIBHDF5) +freespace_SOURCES = freespace.c +freespace_OBJECTS = freespace.$(OBJEXT) +freespace_LDADD = $(LDADD) +freespace_DEPENDENCIES = libh5test.la $(LIBHDF5) gen_bad_ohdr_SOURCES = gen_bad_ohdr.c gen_bad_ohdr_OBJECTS = gen_bad_ohdr.$(OBJEXT) gen_bad_ohdr_LDADD = $(LDADD) @@ -253,6 +258,10 @@ links_SOURCES = links.c links_OBJECTS = links.$(OBJEXT) links_LDADD = $(LDADD) links_DEPENDENCIES = libh5test.la $(LIBHDF5) +mf_SOURCES = mf.c +mf_OBJECTS = mf.$(OBJEXT) +mf_LDADD = $(LDADD) +mf_DEPENDENCIES = libh5test.la $(LIBHDF5) mount_SOURCES = mount.c mount_OBJECTS = mount.$(OBJEXT) mount_LDADD = $(LDADD) @@ -339,26 +348,26 @@ SOURCES = $(libh5test_la_SOURCES) app_ref.c big.c bittests.c btree2.c \ cache.c cache_api.c cmpd_dset.c cross_read.c dangle.c dsets.c \ dt_arith.c dtransform.c dtypes.c enum.c err_compat.c \ error_test.c extend.c external.c fheap.c fillval.c flush1.c \ - flush2.c gen_bad_ohdr.c gen_bogus.c gen_cross.c gen_deflate.c \ - gen_filters.c gen_new_array.c gen_new_fill.c gen_new_group.c \ - gen_new_mtime.c gen_new_super.c gen_noencoder.c \ - gen_nullspace.c gen_udlinks.c getname.c gheap.c hyperslab.c \ - istore.c lheap.c links.c mount.c mtime.c ntypes.c objcopy.c \ - ohdr.c pool.c reserved.c set_extent.c space_overflow.c stab.c \ - $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c \ - vfd.c + flush2.c freespace.c gen_bad_ohdr.c gen_bogus.c gen_cross.c \ + gen_deflate.c gen_filters.c gen_new_array.c gen_new_fill.c \ + gen_new_group.c gen_new_mtime.c gen_new_super.c \ + gen_noencoder.c gen_nullspace.c gen_udlinks.c getname.c \ + gheap.c hyperslab.c istore.c lheap.c links.c mf.c mount.c \ + mtime.c ntypes.c objcopy.c ohdr.c pool.c reserved.c \ + set_extent.c space_overflow.c stab.c $(testhdf5_SOURCES) \ + testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c DIST_SOURCES = $(libh5test_la_SOURCES) app_ref.c big.c bittests.c \ btree2.c cache.c cache_api.c cmpd_dset.c cross_read.c dangle.c \ dsets.c dt_arith.c dtransform.c dtypes.c enum.c err_compat.c \ error_test.c extend.c external.c fheap.c fillval.c flush1.c \ - flush2.c gen_bad_ohdr.c gen_bogus.c gen_cross.c gen_deflate.c \ - gen_filters.c gen_new_array.c gen_new_fill.c gen_new_group.c \ - gen_new_mtime.c gen_new_super.c gen_noencoder.c \ - gen_nullspace.c gen_udlinks.c getname.c gheap.c hyperslab.c \ - istore.c lheap.c links.c mount.c mtime.c ntypes.c objcopy.c \ - ohdr.c pool.c reserved.c set_extent.c space_overflow.c stab.c \ - $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c \ - vfd.c + flush2.c freespace.c gen_bad_ohdr.c gen_bogus.c gen_cross.c \ + gen_deflate.c gen_filters.c gen_new_array.c gen_new_fill.c \ + gen_new_group.c gen_new_mtime.c gen_new_super.c \ + gen_noencoder.c gen_nullspace.c gen_udlinks.c getname.c \ + gheap.c hyperslab.c istore.c lheap.c links.c mf.c mount.c \ + mtime.c ntypes.c objcopy.c ohdr.c pool.c reserved.c \ + set_extent.c space_overflow.c stab.c $(testhdf5_SOURCES) \ + testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -654,7 +663,7 @@ TEST_PROG = testhdf5 lheap ohdr stab gheap cache cache_api \ fillval mount flush1 flush2 app_ref enum \ set_extent ttsafe \ getname vfd ntypes dangle dtransform reserved cross_read \ - btree2 fheap + freespace mf btree2 fheap # These programs generate test files for the tests. They don't need to be @@ -834,6 +843,9 @@ flush1$(EXEEXT): $(flush1_OBJECTS) $(flush1_DEPENDENCIES) flush2$(EXEEXT): $(flush2_OBJECTS) $(flush2_DEPENDENCIES) @rm -f flush2$(EXEEXT) $(LINK) $(flush2_OBJECTS) $(flush2_LDADD) $(LIBS) +freespace$(EXEEXT): $(freespace_OBJECTS) $(freespace_DEPENDENCIES) + @rm -f freespace$(EXEEXT) + $(LINK) $(freespace_OBJECTS) $(freespace_LDADD) $(LIBS) gen_bad_ohdr$(EXEEXT): $(gen_bad_ohdr_OBJECTS) $(gen_bad_ohdr_DEPENDENCIES) @rm -f gen_bad_ohdr$(EXEEXT) $(LINK) $(gen_bad_ohdr_OBJECTS) $(gen_bad_ohdr_LDADD) $(LIBS) @@ -891,6 +903,9 @@ lheap$(EXEEXT): $(lheap_OBJECTS) $(lheap_DEPENDENCIES) links$(EXEEXT): $(links_OBJECTS) $(links_DEPENDENCIES) @rm -f links$(EXEEXT) $(LINK) $(links_OBJECTS) $(links_LDADD) $(LIBS) +mf$(EXEEXT): $(mf_OBJECTS) $(mf_DEPENDENCIES) + @rm -f mf$(EXEEXT) + $(LINK) $(mf_OBJECTS) $(mf_LDADD) $(LIBS) mount$(EXEEXT): $(mount_OBJECTS) $(mount_DEPENDENCIES) @rm -f mount$(EXEEXT) $(LINK) $(mount_OBJECTS) $(mount_LDADD) $(LIBS) @@ -966,6 +981,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fillval.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flush1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flush2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freespace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_bad_ohdr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_bogus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen_cross.Po@am__quote@ @@ -986,6 +1002,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/istore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lheap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/links.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mount.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mtime.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntypes.Po@am__quote@ @@ -80,8 +80,8 @@ randll(hsize_t limit, int current_index) /* does not overlap with any previous writes */ while(overlap != 0 && tries < MAX_TRIES) { - acc = rand (); - acc *= rand (); + acc = HDrandom(); + acc *= HDrandom(); acc = acc % limit; overlap = 0; @@ -294,11 +294,6 @@ writer (char* filename, hid_t fapl, int wrt_n) * or it will take some time to write a file. * We should create a dataset allocating space late and never writing fill values. * EIP 4/8/03 - - if((d1 = H5Dcreate2(file, "d1", H5T_NATIVE_INT, space1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0 || - (d2 = H5Dcreate2(file, "d2", H5T_NATIVE_INT, space2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) { - goto error; - } */ dcpl = H5Pcreate(H5P_DATASET_CREATE); H5Pset_alloc_time(dcpl, H5D_ALLOC_TIME_LATE); @@ -381,14 +376,14 @@ reader(char *filename, hid_t fapl) script = fopen(DNAME, "r"); /* Open HDF5 file */ - if((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) goto error; + if((file = H5Fopen(filename, H5F_ACC_RDONLY, fapl)) < 0) FAIL_STACK_ERROR /* Open the dataset */ - if((d2 = H5Dopen2(file, "d2", H5P_DEFAULT)) < 0) goto error; - if((fspace = H5Dget_space(d2)) < 0) goto error; + if((d2 = H5Dopen2(file, "d2", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + if((fspace = H5Dget_space(d2)) < 0) FAIL_STACK_ERROR /* Describe `buf' */ - if((mspace = H5Screate_simple(1, hs_size, hs_size)) < 0) goto error; + if((mspace = H5Screate_simple(1, hs_size, hs_size)) < 0) FAIL_STACK_ERROR /* Read each region */ while(fgets(ln, (int)sizeof(ln), script)) { @@ -400,9 +395,9 @@ reader(char *filename, hid_t fapl) fflush(stdout); if(H5Sselect_hyperslab(fspace, H5S_SELECT_SET, hs_offset, NULL, - hs_size, NULL) < 0) goto error; + hs_size, NULL) < 0) FAIL_STACK_ERROR if(H5Dread(d2, H5T_NATIVE_INT, mspace, fspace, H5P_DEFAULT, buf) < 0) - goto error; + FAIL_STACK_ERROR /* Check */ for(j = zero = wrong = 0; j < WRT_SIZE; j++) { @@ -423,10 +418,10 @@ reader(char *filename, hid_t fapl) } } - if(H5Dclose(d2) < 0) goto error; - if(H5Sclose(mspace) < 0) goto error; - if(H5Sclose(fspace) < 0) goto error; - if(H5Fclose(file) < 0) goto error; + if(H5Dclose(d2) < 0) FAIL_STACK_ERROR + if(H5Sclose(mspace) < 0) FAIL_STACK_ERROR + if(H5Sclose(fspace) < 0) FAIL_STACK_ERROR + if(H5Fclose(file) < 0) FAIL_STACK_ERROR free(buf); fclose(script); @@ -511,6 +506,7 @@ main (int ac, char **av) hsize_t family_size; hsize_t family_size_def; /* default family file size */ double family_size_def_dbl; /* default family file size */ + unsigned long seed = 0; /* Random # seed */ int cflag=1; /* check file system before test */ char filename[1024]; @@ -547,6 +543,14 @@ main (int ac, char **av) } } + /* Choose random # seed */ + seed = (unsigned long)HDtime(NULL); +#ifdef QAK +/* seed = (unsigned long)1155438845; */ +HDfprintf(stderr, "Random # seed was: %lu\n", seed); +#endif /* QAK */ + HDsrandom(seed); + /* Reset library */ h5_reset(); fapl = h5_fileaccess(); @@ -657,3 +661,4 @@ error: puts("*** TEST FAILED ***"); return 1; } + diff --git a/test/btree2.c b/test/btree2.c index d4347d4..a25a373 100644 --- a/test/btree2.c +++ b/test/btree2.c @@ -76,9 +76,9 @@ iter_cb(const void *_record, void *_op_data) * * Purpose: v2 B-tree find callback * - * Return: Success: 0 + * Return: Success: TRUE/FALSE * - * Failure: 1 + * Failure: FAIL * * Programmer: Quincey Koziol * Thursday, February 24, 2005 @@ -92,9 +92,9 @@ find_cb(const void *_record, void *_op_data) hsize_t *search = (hsize_t *)_op_data; if(*record != *search) - return(-1); + return(FALSE); - return(0); + return(TRUE); } /* end find_cb() */ @@ -261,11 +261,7 @@ test_insert_basic(hid_t fapl) /* Attempt to find record in B-tree with no records */ idx = 0; - H5E_BEGIN_TRY { - ret = H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, NULL); - } H5E_END_TRY; - /* Should fail */ - if(ret != FAIL) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, NULL) != FALSE) TEST_ERROR /* Attempt to index record in B-tree with no records */ @@ -286,29 +282,23 @@ test_insert_basic(hid_t fapl) FAIL_STACK_ERROR /* Attempt to find non-existant record in B-tree with 1 record */ + /* (Should not be found, but not fail) */ idx = 41; - H5E_BEGIN_TRY { - ret = H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx); - } H5E_END_TRY; - /* Should fail */ - if(ret != FAIL) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != FALSE) TEST_ERROR /* Try again with NULL 'op' */ - H5E_BEGIN_TRY { - ret = H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, NULL, NULL); - } H5E_END_TRY; - /* Should fail */ - if(ret != FAIL) + /* (Should not be found, but not fail) */ + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, NULL, NULL) != FALSE) TEST_ERROR /* Attempt to find existant record in B-tree with 1 record */ idx = 42; - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx)<0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != TRUE) TEST_ERROR /* Try again with NULL 'op' */ - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, NULL, NULL)<0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, NULL, NULL) != TRUE) TEST_ERROR /* Attempt to index non-existant record in B-tree with 1 record */ @@ -347,17 +337,14 @@ test_insert_basic(hid_t fapl) FAIL_STACK_ERROR /* Attempt to find non-existant record in level-0 B-tree with several records */ + /* (Should not be found, but not fail) */ idx = 41; - H5E_BEGIN_TRY { - ret = H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx); - } H5E_END_TRY; - /* Should fail */ - if(ret != FAIL) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != FALSE) TEST_ERROR /* Attempt to find existant record in level-0 B-tree with several record */ idx = 56; - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx)<0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != TRUE) TEST_ERROR /* Attempt to index non-existant record in B-tree with several records */ @@ -521,22 +508,19 @@ test_insert_split_root(hid_t fapl) TEST_ERROR /* Attempt to find non-existant record in level-1 B-tree */ + /* (Should not be found, but not fail) */ idx = INSERT_SPLIT_ROOT_NREC + 10; - H5E_BEGIN_TRY { - ret = H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx); - } H5E_END_TRY; - /* Should fail */ - if(ret != FAIL) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != FALSE) TEST_ERROR /* Attempt to find existant record in root of level-1 B-tree */ idx = 33; - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) < 0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != TRUE) FAIL_STACK_ERROR /* Attempt to find existant record in leaf of level-1 B-tree */ idx = 56; - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) < 0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != TRUE) FAIL_STACK_ERROR /* Attempt to index non-existant record in level-1 B-tree */ @@ -1286,17 +1270,14 @@ test_insert_make_level2(hid_t fapl) TEST_ERROR /* Attempt to find non-existant record in level-2 B-tree */ + /* (Should not be found, but not fail) */ idx = INSERT_SPLIT_ROOT_NREC * 30; - H5E_BEGIN_TRY { - ret = H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx); - } H5E_END_TRY; - /* Should fail */ - if(ret != FAIL) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != FALSE) TEST_ERROR /* Attempt to find existant record in root of level-2 B-tree */ idx = 948; - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) < 0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != TRUE) FAIL_STACK_ERROR /* Check with B-tree */ @@ -1308,7 +1289,7 @@ test_insert_make_level2(hid_t fapl) /* Attempt to find existant record in internal node of level-2 B-tree */ idx = 505; - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) < 0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != TRUE) FAIL_STACK_ERROR /* Check with B-tree */ @@ -1320,7 +1301,7 @@ test_insert_make_level2(hid_t fapl) /* Attempt to find existant record in leaf of level-2 B-tree */ idx = 555; - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) < 0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != TRUE) FAIL_STACK_ERROR /* Check with B-tree */ @@ -2838,12 +2819,9 @@ HDfprintf(stderr,"curr_time=%lu\n",(unsigned long)curr_time); TEST_ERROR /* Attempt to find non-existant record in level-4 B-tree */ - idx = INSERT_MANY*2; - H5E_BEGIN_TRY { - ret = H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx); - } H5E_END_TRY; - /* Should fail */ - if(ret != FAIL) + /* (Should not be found, but not fail) */ + idx = INSERT_MANY * 2; + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != FALSE) TEST_ERROR /* Find random records */ @@ -2852,7 +2830,7 @@ HDfprintf(stderr,"curr_time=%lu\n",(unsigned long)curr_time); idx = (hsize_t)(HDrandom()%INSERT_MANY); /* Attempt to find existant record in root of level-4 B-tree */ - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) < 0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &idx, find_cb, &idx) != TRUE) FAIL_STACK_ERROR } /* end for */ @@ -7310,7 +7288,7 @@ test_modify(hid_t fapl) /* Attempt to find modified record */ record = 4331; found = 4331; - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &record, find_cb, &found) < 0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &record, find_cb, &found) != TRUE) FAIL_STACK_ERROR if(found != 4331) TEST_ERROR @@ -7354,7 +7332,7 @@ test_modify(hid_t fapl) /* Attempt to find modified record */ record = 5352; found = 5352; - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &record, find_cb, &found) < 0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &record, find_cb, &found) != TRUE) STACK_ERROR if(found != 5352) TEST_ERROR @@ -7398,7 +7376,7 @@ test_modify(hid_t fapl) /* Attempt to find modified record */ record = 9448; found = 9448; - if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &record, find_cb, &found) < 0) + if(H5B2_find(f, H5P_DATASET_XFER_DEFAULT, H5B2_TEST, bt2_addr, &record, find_cb, &found) != TRUE) STACK_ERROR if(found != 9448) TEST_ERROR diff --git a/test/cache.c b/test/cache.c index 7de613e..bc89102 100644 --- a/test/cache.c +++ b/test/cache.c @@ -16778,7 +16778,7 @@ check_expunge_entry_errs(void) if ( pass ) { result = H5C_expunge_entry(NULL, -1, -1, cache_ptr, - &(types[0]), entry_ptr->addr); + &(types[0]), entry_ptr->addr, H5AC__NO_FLAGS_SET); if ( result > 0 ) { @@ -16796,7 +16796,7 @@ check_expunge_entry_errs(void) if ( pass ) { result = H5C_expunge_entry(NULL, -1, -1, cache_ptr, - &(types[0]), entry_ptr->addr); + &(types[0]), entry_ptr->addr, H5AC__NO_FLAGS_SET); if ( result > 0 ) { @@ -16814,7 +16814,7 @@ check_expunge_entry_errs(void) if ( pass ) { result = H5C_expunge_entry(NULL, -1, -1, cache_ptr, - &(types[0]), entry_ptr->addr); + &(types[0]), entry_ptr->addr, H5AC__NO_FLAGS_SET); if ( result < 0 ) { diff --git a/test/cache_common.c b/test/cache_common.c index 5eb91dc..c2ce274 100644 --- a/test/cache_common.c +++ b/test/cache_common.c @@ -2302,7 +2302,7 @@ expunge_entry(H5C_t * cache_ptr, HDassert( ! ( entry_ptr->is_pinned ) ); result = H5C_expunge_entry(NULL, -1, -1, cache_ptr, &(types[type]), - entry_ptr->addr); + entry_ptr->addr, H5AC__NO_FLAGS_SET); if ( result < 0 ) { diff --git a/test/dsets.c b/test/dsets.c index b22ec27..1121f76 100644 --- a/test/dsets.c +++ b/test/dsets.c @@ -6044,7 +6044,7 @@ test_random_chunks(hid_t fapl) if((m = H5Screate_simple(1, msize, NULL)) < 0) TEST_ERROR; /* Select the random points for writing */ - if(H5Sselect_elements(s, H5S_SELECT_SET, NPOINTS, coord) < 0) TEST_ERROR; + if(H5Sselect_elements(s, H5S_SELECT_SET, NPOINTS, (const hsize_t *)coord) < 0) TEST_ERROR; /* Write into dataset */ if(H5Dwrite(d, H5T_NATIVE_INT, m, s, H5P_DEFAULT, wbuf) < 0) TEST_ERROR; @@ -6069,7 +6069,7 @@ test_random_chunks(hid_t fapl) if((m = H5Screate_simple(1, msize, NULL)) < 0) TEST_ERROR; /* Select the random points for reading */ - if(H5Sselect_elements (s, H5S_SELECT_SET, NPOINTS, coord) < 0) TEST_ERROR; + if(H5Sselect_elements (s, H5S_SELECT_SET, NPOINTS, (const hsize_t *)coord) < 0) TEST_ERROR; /* Read from dataset */ if(H5Dread(d, H5T_NATIVE_INT, m, s, H5P_DEFAULT, rbuf) < 0) TEST_ERROR; @@ -6134,7 +6134,7 @@ test_random_chunks(hid_t fapl) if((m = H5Screate_simple(1, msize, NULL)) < 0) TEST_ERROR; /* Select the random points for writing */ - if(H5Sselect_elements(s, H5S_SELECT_SET, NPOINTS, coord) < 0) TEST_ERROR; + if(H5Sselect_elements(s, H5S_SELECT_SET, NPOINTS, (const hsize_t *)coord) < 0) TEST_ERROR; /* Write into dataset */ if(H5Dwrite(d, H5T_NATIVE_INT, m, s, H5P_DEFAULT, wbuf) < 0) TEST_ERROR; @@ -6159,7 +6159,7 @@ test_random_chunks(hid_t fapl) if((m = H5Screate_simple(1, msize, NULL)) < 0) TEST_ERROR; /* Select the random points for reading */ - if(H5Sselect_elements (s, H5S_SELECT_SET, NPOINTS, coord) < 0) TEST_ERROR; + if(H5Sselect_elements (s, H5S_SELECT_SET, NPOINTS, (const hsize_t *)coord) < 0) TEST_ERROR; /* Read from dataset */ if(H5Dread(d, H5T_NATIVE_INT, m, s, H5P_DEFAULT, rbuf) < 0) TEST_ERROR; diff --git a/test/freespace.c b/test/freespace.c new file mode 100644 index 0000000..c786ebb --- /dev/null +++ b/test/freespace.c @@ -0,0 +1,2805 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* + * Tests for free-space manager + */ +#include "h5test.h" + +#define H5FS_PACKAGE +#define H5FS_TESTING +#include "H5FSpkg.h" /* Free space manager */ + + +/* Other private headers that this test requires */ +#define H5F_PACKAGE +#include "H5Fpkg.h" +#include "H5FLprivate.h" +#include "H5Iprivate.h" +#include "H5Vprivate.h" + +#define FILENAME_LEN 1024 + +#define TEST_FSPACE_CLIENT_ID 2 +#define TEST_FSPACE_SECT_TYPE 0 +#define TEST_FSPACE_SECT_TYPE_NEW 1 +#define TEST_FSPACE_SECT_TYPE_NONE 2 + +#define TEST_FSPACE_SHRINK 80 +#define TEST_FSPACE_EXPAND 120 +#define TEST_MAX_SECT_SIZE (64 * 1024) +#define TEST_MAX_INDEX 32 + +#define TEST_SECT_ADDR60 60 +#define TEST_SECT_ADDR70 70 +#define TEST_SECT_ADDR80 80 +#define TEST_SECT_ADDR100 100 +#define TEST_SECT_ADDR150 150 +#define TEST_SECT_ADDR200 200 +#define TEST_SECT_ADDR300 300 + +#define TEST_SECT_SIZE5 5 +#define TEST_SECT_SIZE10 10 +#define TEST_SECT_SIZE15 15 +#define TEST_SECT_SIZE20 20 +#define TEST_SECT_SIZE30 30 +#define TEST_SECT_SIZE40 40 +#define TEST_SECT_SIZE50 50 +#define TEST_SECT_SIZE80 80 + +#define FSPACE_THRHD_DEF 1 /* Default: no alignment threshold */ +#define FSPACE_ALIGN_DEF 1 /* Default: no alignment */ + +const char *FILENAME[] = { + "frspace", + NULL +}; + +typedef struct frspace_state_t { + hsize_t tot_space; /* Total amount of space tracked */ + hsize_t tot_sect_count; /* Total # of sections tracked */ + hsize_t serial_sect_count; /* # of serializable sections tracked */ + hsize_t ghost_sect_count; /* # of un-serializable sections tracked */ +} frspace_state_t; + +haddr_t g_eoa=0; +static haddr_t TEST_get_eoa(void); +static void TEST_set_eoa(haddr_t); + +/* + * TEST client + */ +typedef struct TEST_free_section_t { + H5FS_section_info_t sect_info; /* Free space section information (must be first in struct) */ +} TEST_free_section_t; + +H5FL_DEFINE(TEST_free_section_t); + + +static herr_t TEST_sect_init_cls(H5FS_section_class_t *, void *); +static herr_t TEST_sect_free(H5FS_section_info_t *_sect); +static herr_t TEST_sect_can_merge(const H5FS_section_info_t *, const H5FS_section_info_t *, void UNUSED *); +static herr_t TEST_sect_merging(H5FS_section_info_t *, H5FS_section_info_t *, void UNUSED *); +static herr_t TEST_sect_can_shrink(const H5FS_section_info_t *, void *); +static herr_t TEST_sect_shrinking(H5FS_section_info_t **, void *); + +H5FS_section_class_t TEST_FSPACE_SECT_CLS[1] = {{ + TEST_FSPACE_SECT_TYPE, /* Section type */ + 0, /* Extra serialized size */ + H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ + TEST_sect_init_cls, /* Initialize section class */ + NULL, /* Terminate section class */ + + /* Object methods */ + NULL, /* Add section */ + NULL, /* Serialize section */ + NULL, /* Deserialize section */ + TEST_sect_can_merge, /* Can sections merge? */ + TEST_sect_merging, /* Merge sections */ + TEST_sect_can_shrink, /* Can section shrink container?*/ + TEST_sect_shrinking, /* Shrink container w/section */ + TEST_sect_free, /* Free section */ + NULL, /* Check validity of section */ + NULL, /* Split section node for alignment */ + NULL, /* Dump debugging for section */ +}}; + +H5FS_section_class_t TEST_FSPACE_SECT_CLS_NEW[1] = {{ + TEST_FSPACE_SECT_TYPE_NEW, /* Section type */ + 0, /* Extra serialized size */ + H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ + TEST_sect_init_cls, /* Initialize section class */ + NULL, /* Terminate section class */ + + /* Object methods */ + NULL, /* Add section */ + NULL, /* Serialize section */ + NULL, /* Deserialize section */ + TEST_sect_can_merge, /* Can sections merge? */ + TEST_sect_merging, /* Merge sections */ + NULL, /* Can section shrink container?*/ + NULL, /* Shrink container w/section */ + TEST_sect_free, /* Free section */ + NULL, /* Check validity of section */ + NULL, /* Split section node for alignment */ + NULL, /* Dump debugging for section */ +}}; + +H5FS_section_class_t TEST_FSPACE_SECT_CLS_NOINIT[1] = {{ + TEST_FSPACE_SECT_TYPE_NONE, /* Section type */ + 0, /* Extra serialized size */ + H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ + NULL, /* Initialize section class */ + NULL, /* Terminate section class */ + + /* Object methods */ + NULL, /* Add section */ + NULL, /* Serialize section */ + NULL, /* Deserialize section */ + TEST_sect_can_merge, /* Can sections merge? */ + TEST_sect_merging, /* Merge sections */ + NULL, /* Can section shrink container?*/ + NULL, /* Shrink container w/section */ + TEST_sect_free, /* Free section */ + NULL, /* Check validity of section */ + NULL, /* Split section node for alignment */ + NULL, /* Dump debugging for section */ +}}; + +const H5FS_section_class_t *test_classes[] = { + TEST_FSPACE_SECT_CLS, + TEST_FSPACE_SECT_CLS_NEW, + TEST_FSPACE_SECT_CLS_NOINIT +}; + + +static void init_cparam(H5FS_create_t *); +static void init_sect_node(TEST_free_section_t *, haddr_t, hsize_t, unsigned, H5FS_section_state_t); +static int check_stats(const H5FS_t *, const frspace_state_t *); + +#define NUM_SECTIONS 1000 + +/* User data for free space section iterator callback */ +typedef struct { + hsize_t tot_size; + hsize_t tot_sect_count; +} TEST_iter_ud_t; + +static herr_t TEST_sects_cb(const H5FS_section_info_t *_sect, void *_udata); + + +/* + * Tests + */ +static int test_fs_create(hid_t); +static int test_fs_sect_add(hid_t); +static int test_fs_sect_merge(hid_t); +static int test_fs_sect_shrink(hid_t); +static int test_fs_sect_find(hid_t); +static int test_fs_sect_change_class(hid_t); +static int test_fs_sect_extend(hid_t); +static int test_fs_sect_iterate(hid_t); + +/* + * free-space section routines for client TEST + */ +static herr_t +TEST_sect_init_cls(H5FS_section_class_t *cls, void *_udata) +{ + herr_t ret_value = SUCCEED; /* Return value */ + unsigned *init_flags; + + /* Check arguments. */ + HDassert(cls); + HDassert(_udata); + + init_flags = (unsigned *)_udata; + cls->flags |= *init_flags; + + return(ret_value); +} /* TEST_sect_init_cls() */ + +/* + * Check if the two sections can be merged: + * true if second section adjoins the first section + */ +static herr_t +TEST_sect_can_merge(const H5FS_section_info_t *_sect1, + const H5FS_section_info_t *_sect2, void UNUSED *_udata) +{ + const TEST_free_section_t *sect1 = (const TEST_free_section_t *)_sect1; + const TEST_free_section_t *sect2 = (const TEST_free_section_t *)_sect2; + htri_t ret_value; /* Return value */ + + /* Check arguments. */ + HDassert(sect1); + HDassert(sect2); + HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */ + HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); + + /* Check if second section adjoins first section */ + ret_value = H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr); + + return(ret_value); +} /* TEST_sect_can_merge() */ + +/* + * Merge the two sections (second section is merged into the first section) + */ +static herr_t +TEST_sect_merging(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, + void UNUSED *_udata) +{ + TEST_free_section_t *sect1 = (TEST_free_section_t *)_sect1; + TEST_free_section_t *sect2 = (TEST_free_section_t *)_sect2; + herr_t ret_value = SUCCEED; /* Return value */ + + /* Check arguments. */ + HDassert(sect1); + HDassert((sect1->sect_info.type == TEST_FSPACE_SECT_TYPE) || + (sect1->sect_info.type == TEST_FSPACE_SECT_TYPE_NEW) || + (sect1->sect_info.type == TEST_FSPACE_SECT_TYPE_NONE)); + HDassert(sect2); + HDassert((sect2->sect_info.type == TEST_FSPACE_SECT_TYPE) || + (sect2->sect_info.type == TEST_FSPACE_SECT_TYPE_NEW) || + (sect2->sect_info.type == TEST_FSPACE_SECT_TYPE_NONE)); + HDassert(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr)); + + /* Add second section's size to first section */ + sect1->sect_info.size += sect2->sect_info.size; + + /* Get rid of second section */ + if(TEST_sect_free((H5FS_section_info_t *)sect2) < 0) + TEST_ERROR +error: + return(ret_value); +} /* TEST_sect_merging() */ + +/* + * Free the section + */ +static herr_t +TEST_sect_free(H5FS_section_info_t *_sect) +{ + TEST_free_section_t *sect = (TEST_free_section_t *)_sect; + + /* Release the section */ + H5FL_FREE(TEST_free_section_t, sect); + + return(0); +} /* TEST_sect_free() */ + +/* + * Determine if the section can be shrunk and set _udata accordingly + * if _udata passed in is NULL, return FALSE + * Otherwise: + * if section's address+size is the end of file, return TRUE + * otherwise return FALSE + */ +static herr_t +TEST_sect_can_shrink(const H5FS_section_info_t *_sect, void *_udata) +{ + unsigned *can_shrink = (unsigned *)_udata; + const TEST_free_section_t *sect = (const TEST_free_section_t *)_sect; + haddr_t end, eoa; + + if (can_shrink == NULL) + return(FALSE); + + end = sect->sect_info.addr + sect->sect_info.size; + eoa = TEST_get_eoa(); + + if (end == eoa) + *can_shrink = TRUE; + else + *can_shrink = FALSE; + return(*can_shrink); + +} /* TEST_sect_can_shrink() */ + +/* + * Shrink the section + */ +static herr_t +TEST_sect_shrinking(H5FS_section_info_t **_sect, void *_udata) +{ + TEST_free_section_t **sect = (TEST_free_section_t **)_sect; + unsigned *can_shrink = (unsigned *)_udata; + + /* address of the section is faked, so, doesn't need to do anything */ + /* just free the section node */ + if (*can_shrink) { + if (TEST_sect_free((H5FS_section_info_t *)*sect) < 0) + TEST_ERROR + *sect = NULL; + return(TRUE); + } + +error: + return(FALSE); +} + + +/* + * iteration callback + */ +static herr_t +TEST_sects_cb(const H5FS_section_info_t *_sect, void *_udata) +{ + const TEST_free_section_t *sect = (const TEST_free_section_t *)_sect; + TEST_iter_ud_t *udata = (TEST_iter_ud_t *)_udata; + herr_t ret_value = SUCCEED; /* Return value */ + + HDassert(sect); + HDassert(udata); + + udata->tot_size += sect->sect_info.size; + udata->tot_sect_count += 1; + + return(ret_value); +} + +/* supporting routine for shrinking */ +static haddr_t +TEST_get_eoa(void) +{ + return(g_eoa); +} + +/* supporting routine for shrinking */ +static void +TEST_set_eoa(haddr_t val) +{ + g_eoa = val; +} + +/* + * Initialize creation parameter structure for TEST client + */ +static void +init_cparam(H5FS_create_t *cparam) +{ + HDmemset(cparam, 0, sizeof(H5FS_create_t)); + + /* Set the free space creation parameters */ + cparam->shrink_percent = TEST_FSPACE_SHRINK; + cparam->expand_percent = TEST_FSPACE_EXPAND; + cparam->max_sect_size = TEST_MAX_SECT_SIZE; + cparam->max_sect_addr = TEST_MAX_INDEX; + +} /* init_cparam() */ + +/* + * Initialize free space section node + */ +static void +init_sect_node(TEST_free_section_t *sect_node, haddr_t addr, hsize_t size, unsigned type, H5FS_section_state_t state) +{ + sect_node->sect_info.addr = addr; + sect_node->sect_info.size = size; + sect_node->sect_info.type = type; + sect_node->sect_info.state = state; +} /* init_sect_node() */ + +/* + * Verify statistics for the free-space manager + */ +static int +check_stats(const H5FS_t *frsp, const frspace_state_t *state) +{ + H5FS_stat_t frspace_stats; /* Statistics about the heap */ + + /* Get statistics for heap and verify they are correct */ + if(H5FS_stat_info(frsp, &frspace_stats) < 0) + FAIL_STACK_ERROR + + if(frspace_stats.tot_space != state->tot_space) { + HDfprintf(stdout, "frspace_stats.tot_space = %Hu, state->tot_space = %Zu\n", + frspace_stats.tot_space, state->tot_space); + TEST_ERROR + } /* end if */ + if(frspace_stats.tot_sect_count != state->tot_sect_count) { + HDfprintf(stdout, "frspace_stats.tot_sect_count = %Hu, state->tot_sect_count = %Hu\n", + frspace_stats.tot_sect_count, state->tot_sect_count); + TEST_ERROR + } /* end if */ + if(frspace_stats.serial_sect_count != state->serial_sect_count) { + HDfprintf(stdout, "frspace_stats.serial_sect_count = %Hu, state->serial_sect_count = %Hu\n", + frspace_stats.serial_sect_count, state->serial_sect_count); + TEST_ERROR + } /* end if */ + if(frspace_stats.ghost_sect_count != state->ghost_sect_count) { + HDfprintf(stdout, "frspace_stats.ghost_sect_count = %Hu, state->ghost_sect_count = %Hu\n", + frspace_stats.ghost_sect_count, state->ghost_sect_count); + TEST_ERROR + } /* end if */ + + /* All tests passed */ + return(0); + +error: + return(1); +} /* check_stats() */ + +/* + * TESTS for free-space manager + */ + +/* + * To verify the creation, close, reopen and deletion of the free-space manager + */ +static int +test_fs_create(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr; /* address of free space */ + h5_stat_size_t file_size, empty_size; /* File size */ + frspace_state_t state; /* State of free space*/ + H5FS_create_t cparam, test_cparam; /* creation parameters */ + size_t nclasses; + unsigned init_flags=0; + + TESTING("the creation/close/reopen/deletion of the free-space manager"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* initialize creation parameters for free-space manager */ + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + if (frsp->nclasses != nclasses) + TEST_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + if(check_stats(frsp, &state)) + TEST_ERROR + + HDmemset(&test_cparam, 0, sizeof(H5FS_create_t)); + if(H5FS_get_cparam_test(frsp, &test_cparam) < 0) + FAIL_STACK_ERROR + if (H5FS_cmp_cparam_test(&cparam, &test_cparam)) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* reopen the free-space manager */ + if(NULL == (frsp = H5FS_open(f, H5P_DATASET_XFER_DEFAULT, fs_addr, + nclasses, test_classes, NULL, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + if (frsp->nclasses != nclasses) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(file_size != empty_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_fs_create() */ + + +/* + * Test 1: + * Create free-space manager + * Add section A via H5FS_sect_add() with H5FS_ADD_RETURNED_SPACE + * Close the free-space manager + * Result: section A is serialized to the file + * + * Test 2: + * Create free-space manager with H5FS_CLS_GHOST_OBJ section class setting + * Add section A via H5FS_sect_add() with H5FS_ADD_RETURNED_SPACE + * Close the free-space manager + * Result: section A is not serialized to the file + * + * Test 3: + * Add section A via H5FS_sect_add() to allow shrinking with H5FS_ADD_RETURNED_SPACE + * Set EOF to be the ending address of section A + * Result: H5FS_sect_add() will shrink section A + * + * Test 4: + * Add section A via H5FS_sect_add() to allow shrinking with H5FS_ADD_DESERIALIZING + * Set EOF to be the ending address of section A + * Result: H5FS_sect_add() will not shrink section A + * + */ +static int +test_fs_sect_add(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node; + unsigned init_flags=0; + h5_stat_size_t file_size=0, tmp_file_size=0, fr_meta_size=0; + unsigned can_shrink=FALSE; + + TESTING("adding a section via H5FS_sect_add() to free-space: test 1"); + + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file w/empty heap*/ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + if(NULL == (sect_node = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE20, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + fr_meta_size = H5FS_HEADER_SIZE(f) + H5FS_SINFO_PREFIX_SIZE(f); + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file w/empty heap*/ + if((tmp_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + if (tmp_file_size <= (file_size+fr_meta_size)) + TEST_ERROR + + PASSED() + + TESTING("adding a section via H5FS_sect_add() to free-space with H5FS_CLS_GHOST_OBJ: test 2"); + + /* Get the size of a file w/empty heap*/ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = H5FS_CLS_GHOST_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* Create free list section node */ + if(NULL == (sect_node = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE20, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node, + 0, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node->sect_info.size; + state.tot_sect_count += 1; + state.ghost_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + fr_meta_size = H5FS_HEADER_SIZE(f); + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file w/empty heap*/ + if((tmp_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + if (tmp_file_size != (file_size+fr_meta_size)) + TEST_ERROR + + PASSED() + + TESTING("adding a section via H5FS_sect_add() to free-space: test 3"); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file w/empty heap*/ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + TEST_set_eoa((haddr_t)TEST_SECT_ADDR150); /* set end of file address for shrinking */ + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = 0; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + if(NULL == (sect_node = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + /* + * Add section A + */ + init_sect_node(sect_node, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + /* nothing in free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("adding a section via H5FS_sect_add() to free-space: test 4"); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file w/empty heap*/ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + TEST_set_eoa((haddr_t)TEST_SECT_ADDR150); /* set end of file address for shrinking */ + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = 0; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + if(NULL == (sect_node = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + /* + * Add section A + */ + init_sect_node(sect_node, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node, + H5FS_ADD_DESERIALIZING, &can_shrink)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_fs_sect_add() */ + + +/* + * To verify the finding of a section with the requested-size from free-space + * + * Test 1: Free-space is empty and is not able to fulfill the requested-size + * Set up: free-space is started up but is empty + * + * Test 2: Add a section and find the section whose size is equal to the requested-size + * Set up: Add section A whose size is less than requested-size + * Add section B whose size is the same as requested-size with addr=b + * Add section C whose size is the same as requested-size with addr=c > b + * Add section D whose size is greater than requested-size + * + * Test 3: Add a section and find the section whose size is > requested-size + * Set up: Add section A whose size is less than requested-size + * Add section B whose size is greater than requested-size + * + * Test 4: Add a section but the section is not able to fulfill the requested-size + * Set up: Add section A whose size is less than requested-size + * + */ +static int +test_fs_sect_find(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node1, *sect_node2, *sect_node3, *sect_node4; + TEST_free_section_t *node; + htri_t node_found = FALSE; + unsigned init_flags=0; + + TESTING("H5FS_sect_find(): free-space is empty"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + + if(check_stats(frsp, &state)) + TEST_ERROR + + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE30, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + PASSED() + + TESTING("H5FS_sect_find() a section equal to requested-size from free-space"); + + /* reopen the free-space manager */ + if(NULL == (frsp = H5FS_open(f, H5P_DATASET_XFER_DEFAULT, fs_addr, nclasses, + test_classes, NULL, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + if (frsp->nclasses != nclasses) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + + /* + * Add section C + */ + if(NULL == (sect_node3 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node3, (haddr_t)(TEST_SECT_ADDR200), (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node3->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section D + */ + if(NULL == (sect_node4 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node4, (haddr_t)TEST_SECT_ADDR300, (hsize_t)TEST_SECT_SIZE80, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node4, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node4->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE50, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR100) || (node->sect_info.size != TEST_SECT_SIZE50)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* remove sections A, C and D */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1) < 0) + FAIL_STACK_ERROR + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3) < 0) + FAIL_STACK_ERROR + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node4) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + PASSED() + + TESTING("H5FS_sect_find() a section greater than requested-size from free-space"); + + /* reopen the free-space manager */ + if(NULL == (frsp = H5FS_open(f, H5P_DATASET_XFER_DEFAULT, fs_addr, nclasses, + test_classes, NULL, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + if (frsp->nclasses != nclasses) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR200, (hsize_t)TEST_SECT_SIZE80, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE50, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + if ((node->sect_info.addr != TEST_SECT_ADDR200) || (node->sect_info.size < TEST_SECT_SIZE50)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* remove sections A */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + PASSED() + + TESTING("H5FS_sect_find(): cannot find a section with requested-size from free-space"); + + /* reopen the free-space manager */ + if(NULL == (frsp = H5FS_open(f, H5P_DATASET_XFER_DEFAULT, fs_addr, nclasses, + test_classes, NULL, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + if (frsp->nclasses != nclasses) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE50, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* remove sections A */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_fs_sect_find() */ + + +/* + * To verify that sections are merged when adding sections to free-space + * + * Test 1: + * Set up: + * H5FS_CLS_SEPAR_OBJ (cls->flags) is not set + * H5FS_ADD_RETURNED_SPACE is passed to H5FS_sect_add() + * + * Add sections C, B, A & D that can be merged together + * + * Test 2: + * Set up: + * H5FS_CLS_SEPAR_OBJ (cls->flags) is set + * H5FS_ADD_RETURNED_SPACE is passed to H5FS_sect_add() + * + * Add sections A & B that can be merged together but cannot do so because H5FS_CLS_SEPAR_OBJ flag is set + * + * Test 3: + * Set up: + * H5FS_CLS_SEPAR_OBJ (cls->flags) is not set + * H5FS_ADD_RETURNED_SPACE is passed to H5FS_sect_add() + * + * Add 4 sections that adjoin each other as follows: + * section A is of section class type A + * section B is of section class type B + * section C is of section class type B + * section D is of section class type A + * Sections B & C are merged together but not section A nor D because: + * sections B & C are merged because of the same section class type + * section A cannot be merged with the merged section of B & C because of different section class type + * section D cannot be merged with the merged section of B & C because of different section class type + */ +static int +test_fs_sect_merge(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node1=NULL, *sect_node2=NULL, *sect_node3=NULL, *sect_node4=NULL; + unsigned init_flags=0; + htri_t node_found = FALSE; + TEST_free_section_t *node; + + TESTING("the merge of sections when H5FS_sect_add() to free-space: test 1"); + + /* + * TEST 1 + */ + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section C + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_SECT_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* section B & C are merged */ + state.tot_space += TEST_SECT_SIZE30; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node3 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node3, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE10, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* section A is merged with the merged section of B & C */ + state.tot_space += TEST_SECT_SIZE10; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section D + */ + if(NULL == (sect_node4 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node4, (haddr_t)TEST_SECT_ADDR150, (hsize_t)TEST_SECT_SIZE80, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node4, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* section D is merged with the merged section of A & B & C */ + state.tot_space += TEST_SECT_SIZE80; + + if(check_stats(frsp, &state)) + TEST_ERROR + + + /* should be able to find the merged section of A, B, C & D */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE10+TEST_SECT_SIZE30+TEST_SECT_SIZE50+TEST_SECT_SIZE80), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + if ((node->sect_info.addr != TEST_SECT_ADDR60) || + (node->sect_info.size != (TEST_SECT_SIZE10+TEST_SECT_SIZE30+TEST_SECT_SIZE50+TEST_SECT_SIZE80))) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + /* + * TEST 2 + */ + TESTING("the merge of sections when H5FS_sect_add() to free-space: test 2"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = H5FS_CLS_SEPAR_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_SECT_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* section A & B are not merged because H5FS_CLS_SEPAR_OBJ is set */ + state.tot_space += TEST_SECT_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* should not be able to find the merged section of A & B */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE30+TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* remove section A from free-space */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1) < 0) + FAIL_STACK_ERROR + /* remove section B from free-space */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + /* + * TEST 3 + */ + TESTING("the merge of sections when H5FS_sect_add() to free-space: test 3"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = 0; /* reset */ + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE10, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_SECT_SIZE10; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE_NEW, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* sections A & B are not merged because H5FS_CLS_MERGE_SYM is set & section class type is different */ + state.tot_space += TEST_SECT_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section C + */ + if(NULL == (sect_node3 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node3, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE_NEW, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* sections B & C are merged because H5FS_CLS_MERGE_SYM is set & section class type is the same */ + state.tot_space += TEST_SECT_SIZE50; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section D + */ + if(NULL == (sect_node4 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node4, (haddr_t)TEST_SECT_ADDR150, (hsize_t)TEST_SECT_SIZE80, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node4, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* + * section D is not merged with the merged section of B & C because + * H5FS_CLS_MERGE_SYM is set and section class type is different + */ + state.tot_space += TEST_SECT_SIZE80; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* should not be able to find a merged section of A, B, C & D */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE10+TEST_SECT_SIZE30+TEST_SECT_SIZE50+TEST_SECT_SIZE80), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* should be able to find the merged section of B & C */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE30+TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR70) || + (node->sect_info.size != (TEST_SECT_SIZE30+TEST_SECT_SIZE50))) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* should be able to find section A */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE10), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR60) || (node->sect_info.size != TEST_SECT_SIZE10)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* should be able to find section D */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE80), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR150) || (node->sect_info.size != TEST_SECT_SIZE80)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_fs_sect_merge() */ + +/* + * To verify that sections are shrunk when adding sections to free-space + * + * Test 1: + * Set EOF to be the ending address of section A + * H5FS_CLS_SEPAR_OBJ (cls->flags) is not set when creating free-space manager + * Add section A to allow shrinking but is not shrunk because its section class type + * TEST_FSPACE_SECT_TYPE_NEW does not define "can_shrink" + * Result:section A is not shrunk and section A is still in free-space + * + * Re-add section A to allow shrinking and with section class type TEST_FSPACE_SECT_TYPE + * that defines "can_shrink" + * Result:section A is shrunk and there is nothing in free-space + * + * Test 2: + * Set EOF to be greater than the ending address of section A + * Set H5FS_CLS_SEPAR_OBJ (cls->flags) when creating free-space manager + * + * Add section A to allow shrinking but is not shrunk because it is not at EOF, + * and section A is not on the merge list due to H5FS_CLS_SEPAR_OBJ + * Add section B to allow shrinking and whose ending address is the same as eof. + * Section B is not merged with section A because of H5FS_CLS_SEPAR_OBJ but it is shrunk + * Result: section A is still in free-space + * + * Test 3: + * Set EOF to be greater than the ending address of section A + * H5FS_CLS_SEPAR_OBJ (cls->flags) is not set when creating free-space manager + * + * Add section A to allow shrinking but is not shrunk because it is not at EOF, + * and section A is on the merge list + * Add section B to allow shrinking and whose ending address is the same as eof. + * Section B is merged with section A and then shrunk. + * Result: free-space should be empty + */ +static int +test_fs_sect_shrink(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node1=NULL, *sect_node2=NULL; + unsigned init_flags=0; + unsigned can_shrink=FALSE; + htri_t node_found = FALSE; + TEST_free_section_t *node; + + TESTING("shrinking of sections when H5FS_sect_add() to free-space: test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + TEST_set_eoa((haddr_t)TEST_SECT_ADDR150); /* set end of file address for shrinking */ + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A that allow shrinking but its section class type does not define "can_shrink" + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE_NEW, H5FS_SECT_LIVE); + + can_shrink = FALSE; + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* section A should still be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR100) || (node->sect_info.size != TEST_SECT_SIZE50)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* + * Re-add section A that allow shrinking and its section class type defines "can_shrink" + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + can_shrink = FALSE; + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + /* should have nothing in free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* section A should not be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + + TESTING("shrinking of sections when H5FS_sect_add() to free-space: test 2"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + TEST_set_eoa((haddr_t)TEST_SECT_ADDR150); /* set end of file address for shrinking */ + + /* does not allow merging */ + init_flags = H5FS_CLS_SEPAR_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE20, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + /* free-space should be the same since section B is shrunk */ + if(check_stats(frsp, &state)) + TEST_ERROR + + /* section B should not be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + if(check_stats(frsp, &state)) + TEST_ERROR + + + /* section A should still be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE20), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR80) || (node->sect_info.size != TEST_SECT_SIZE20)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("shrinking of sections when H5FS_sect_add() to free-space: test 3"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + TEST_set_eoa((haddr_t)TEST_SECT_ADDR150); /* set end of file address for shrinking */ + + init_flags = 0; /* reset */ + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + /* section A & B are merged and then strunk, so there is nothing in free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + if(check_stats(frsp, &state)) + TEST_ERROR + + /* section B should not be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* section A should not be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE30), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_sect_shrink() */ + +/* + * To verify a section's class is changed via H5FS_sect_change_class() + * + * Test 1: + * Add section A with TEST_FSPACE_SECT_TYPE class type with H5FS_CLS_GHOST_OBJ setting + * Add section B with TEST_FSPACE_SECT_TYPE_NONE class type without H5FS_CLS_GHOST_OBJ setting + * Change section A's class to the second section's class + * Result: serial_sect_count is incremented by 1; ghost_sect_count is decremented by 1 + * + * Test 2: + * Add section A with TEST_FSPACE_SECT_TYPE class type with H5FS_CLS_SEPAR_OBJ setting + * Add section B with TEST_FSPACE_SECT_TYPE_NONE class type without H5FS_CLS_SEPAR_OBJ setting + * Add section C with TEST_FSPACE_SECT_TYPE_NONE class type without H5FS_CLS_SEPAR_OBJ setting + * Sections B & C are on the merge list + * Change section class of B and C to A's section class + * Result: the merge list should be null and the class of sections B & C should be changed + */ +static int +test_fs_sect_change_class(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node1=NULL, *sect_node2=NULL, *sect_node3=NULL; + unsigned init_flags=0; + TEST_free_section_t *node; + htri_t node_found = FALSE; + + TESTING("the change of section class via H5FS_sect_change_class() in free-space: Test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = H5FS_CLS_GHOST_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_SECT_SIZE30; + state.tot_sect_count += 1; + state.ghost_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE_NONE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += TEST_SECT_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + if (H5FS_sect_change_class(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + TEST_FSPACE_SECT_TYPE_NONE) < 0) + TEST_ERROR + + state.serial_sect_count += 1; + state.ghost_sect_count -=1; + if(check_stats(frsp, &state)) + TEST_ERROR + + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE30, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node->sect_info.type != TEST_FSPACE_SECT_TYPE_NONE) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + /* + * TEST 2 + */ + TESTING("the merge of sections when H5FS_sect_add() to free-space: test 2"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = H5FS_CLS_SEPAR_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE_NONE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* + * Add section C + */ + if(NULL == (sect_node3 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node3, (haddr_t)TEST_SECT_ADDR200, (hsize_t)TEST_SECT_SIZE80, TEST_FSPACE_SECT_TYPE_NONE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* change the class of B to A's class */ + if (H5FS_sect_change_class(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + TEST_FSPACE_SECT_TYPE) < 0) + TEST_ERROR + + /* change the class of C to A's class */ + if (H5FS_sect_change_class(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3, + TEST_FSPACE_SECT_TYPE) < 0) + TEST_ERROR + + /* the merge_list should be empty */ + if (frsp->sinfo->merge_list) + if (H5SL_count(frsp->sinfo->merge_list)) + TEST_ERROR + + /* verify that section B has changed class */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE50, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node->sect_info.type != TEST_FSPACE_SECT_TYPE) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* verify that section C has changed class */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE80, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node->sect_info.type != TEST_FSPACE_SECT_TYPE) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* remove section A from free-space */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_sect_change_class() */ + + +/* + * To verify the extension of a block using space from a section in free-space + * + * Test 1: Try to extend the block by requested-size, which is equal to section B's size + * Add section A (addr=70, size=5) + * Add section B (addr=100, size=40) + * Try to extend the block (addr=80, size=20) by 40, which is the same as section B's size + * Result: succeed in extending the block + * + * Test 2: Try to extend the block by requested-size, which is greater than section B's size + * Add section A (addr=70, size=5) + * Add section B (addr=100, size=40) + * Try to extend the block (addr=80, size=20) by 50, which is greater than section B's size + * Result: fail in extending the block + * + * Test 3: Try to extend the block by requested-size, which is less than section B's size + * Add section A (addr=70, size=5) + * Add section B (addr=100, size=40) + * Try to extend the block (addr=80, size=20) by 30, which is less than section B's size + * Result: succeed in extending the block and a section of size=10 is left in free-space + * + * Test 4: Try to extend the block which does not adjoin section B + * Add section A (addr=70, size=5) + * Add section B (addr=100, size=40) + * Try to extend the block (addr=80, size=15) by 40 + * Result: fail in extending the block because: + * the block does not adjoin section B (80+15 != addr of section B (80)) + * even though the requested-size is equal to section B's size + * + */ +static int +test_fs_sect_extend(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node1=NULL, *sect_node2=NULL; + unsigned init_flags=0; + + TESTING("a block's extension by requested-size which is = adjoining free section's size: Test 1"); + + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* + * TEST 1 + */ + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE5, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE40, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Extend a block by requested-size */ + if(H5FS_sect_try_extend(f, H5P_DATASET_XFER_DEFAULT, frsp, (haddr_t)TEST_SECT_SIZE80, (hsize_t)TEST_SECT_SIZE20, (hsize_t)TEST_SECT_SIZE40) < 0) + TEST_ERROR + + /* Succeed in extending the block: free space info is decremented accordingly */ + state.tot_space -= sect_node2->sect_info.size; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + PASSED() + + /* + * TEST 2 + */ + TESTING("a block's extension by requested-size which is > adjoining free section's size: Test 2"); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE5, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE40, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Extend the block by requested-size */ + if(H5FS_sect_try_extend(f, H5P_DATASET_XFER_DEFAULT, frsp, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE20, (hsize_t)TEST_SECT_SIZE50) < 0) + TEST_ERROR + + /* Not able to extend the block: free space info remains the same */ + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + PASSED() + + /* + * Test 3 + */ + TESTING("a block's extension by requested-size which is < adjoining free section's size: Test 3"); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE5, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE40, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Extend the block by requested-size */ + if(H5FS_sect_try_extend(f, H5P_DATASET_XFER_DEFAULT, frsp, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE20, (hsize_t)TEST_SECT_SIZE30) < 0) + TEST_ERROR + + /* Succeed in extending the block: total free space is decreased but other info remains the same */ + state.tot_space -= 30; + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + PASSED() + + /* + * TEST 4 + */ + TESTING("a block's extension by requested-size which does not adjoin any free section: Test 4"); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE5, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE40, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Extend the block by requested-size */ + if(H5FS_sect_try_extend(f, H5P_DATASET_XFER_DEFAULT, frsp, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE15, (hsize_t)TEST_SECT_SIZE40) < 0) + TEST_ERROR + + /* Not able to extend the block: free space manager info remains the same */ + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + PASSED() + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_sect_extend() */ + + +/* + * To verify the iteration of free-space sections + * + * Create free-space manager with H5FS_CLS_SEPAR_OBJ + * Create a whole bunch of sections + * Iterate through all sections and collect size and count for all sections + * Check info with H5FS_sect_stat() + */ +static int +test_fs_sect_iterate(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + + TEST_free_section_t *sect_node=NULL; + unsigned init_flags=0, sect_size; + TEST_iter_ud_t udata; + int i; + hsize_t tot_space, nsects; + + TESTING("iteration of sections in the free-space manager"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + udata.tot_size = 0; + udata.tot_sect_count = 0; + + init_flags = H5FS_CLS_SEPAR_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + for (i = 1; i <= NUM_SECTIONS; i++) { + if(NULL == (sect_node = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + sect_size = ((i-1) % 9) + 1; + init_sect_node(sect_node, (haddr_t)i*10, (hsize_t)sect_size, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + } + + if(H5FS_sect_iterate(f, H5P_DATASET_XFER_DEFAULT, frsp, TEST_sects_cb, &udata) < 0) + TEST_ERROR + + H5FS_sect_stats(frsp, &tot_space, &nsects); + + if (udata.tot_size != tot_space) + TEST_ERROR + if (udata.tot_sect_count != nsects) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_fs_sect_iterate() */ + + +int +main(void) +{ + + hid_t fapl = -1; /* File access property list for data files */ + unsigned nerrors = 0; /* Cumulative error count */ + + fapl = h5_fileaccess(); + + /* make sure alignment is not set for tests to succeed */ + if(H5Pset_alignment(fapl, (hsize_t)1, (hsize_t)1) < 0) + TEST_ERROR + + nerrors += test_fs_create(fapl); + nerrors += test_fs_sect_add(fapl); + nerrors += test_fs_sect_merge(fapl); + nerrors += test_fs_sect_shrink(fapl); + nerrors += test_fs_sect_find(fapl); + nerrors += test_fs_sect_change_class(fapl); + nerrors += test_fs_sect_extend(fapl); + nerrors += test_fs_sect_iterate(fapl); + + if(nerrors) + goto error; + puts("All free-space tests passed."); + +#ifdef OUT + h5_cleanup(FILENAME, fapl); +#endif + return (0); + +error: + puts("*** TESTS FAILED ***"); + H5E_BEGIN_TRY { + H5Pclose(fapl); + } H5E_END_TRY; + return (1); +} /* main() */ diff --git a/test/getname.c b/test/getname.c index 2d19d33..4084f9e 100644 --- a/test/getname.c +++ b/test/getname.c @@ -2725,7 +2725,7 @@ test_reg_ref(hid_t fapl) /* Create a reference to elements selection */ if((status = H5Sselect_none(space_id)) < 0) TEST_ERROR - if((status = H5Sselect_elements(space_id, H5S_SELECT_SET, num_points, coord)) < 0) + if((status = H5Sselect_elements(space_id, H5S_SELECT_SET, num_points, (const hsize_t *)coord)) < 0) TEST_ERROR if((status = H5Rcreate(&ref[1], file_id, REFREG_DSETNAMEV, H5R_DATASET_REGION, space_id)) < 0) TEST_ERROR diff --git a/test/links.c b/test/links.c index 4dd6d82..68c7f61 100644 --- a/test/links.c +++ b/test/links.c @@ -26,10 +26,11 @@ */ #define H5G_PACKAGE #define H5G_TESTING -#include "H5Gpkg.h" /* Groups */ #include "h5test.h" -#include "H5Lprivate.h" +#include "H5Gpkg.h" /* Groups */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Lprivate.h" /* Links */ /* File for external link test. Created with gen_udlinks.c */ #define LINKED_FILE "be_extlink2.h5" @@ -1762,6 +1763,10 @@ external_link_root(hid_t fapl, hbool_t new_format) if(H5Gclose(gid) < 0) TEST_ERROR if(H5Fclose(fid) < 0) TEST_ERROR + /* Check that all file IDs have been closed */ + if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) TEST_ERROR + /* Open first file again with read-only access and check on objects created */ if((fid = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) TEST_ERROR @@ -1782,6 +1787,10 @@ external_link_root(hid_t fapl, hbool_t new_format) /* Close first file */ if(H5Fclose(fid) < 0) TEST_ERROR + /* Check that all file IDs have been closed */ + if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) TEST_ERROR + /* Verify that new objects can't be created through a read-only external * link. */ @@ -1795,6 +1804,10 @@ external_link_root(hid_t fapl, hbool_t new_format) /* Close second file again */ if(H5Fclose(fid) < 0) TEST_ERROR + /* Check that all file IDs have been closed */ + if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) TEST_ERROR + PASSED(); return 0; @@ -10377,7 +10390,7 @@ open_by_idx_check(hid_t main_group_id, hid_t soft_group_id, hid_t mount_file_id, haddr_t *objno) { char mntname[NAME_BUF_SIZE]; /* Link value */ - hid_t group_id; /* ID of group to test */ + hid_t group_id = (-1); /* ID of group to test */ H5O_info_t oi; /* Buffer for querying object's info */ haddr_t mnt_root_addr; /* Address of root group in file to mount */ hid_t obj_id; /* ID of object opened */ @@ -10845,7 +10858,7 @@ object_info_check(hid_t main_group_id, hid_t soft_group_id, H5_index_t idx_type, H5_iter_order_t order, unsigned max_links, haddr_t *objno) { char objname[NAME_BUF_SIZE]; /* Object name */ - hid_t group_id; /* ID of group to test */ + hid_t group_id = (-1); /* ID of group to test */ H5O_info_t oinfo; /* Buffer for querying object's info */ unsigned u, v; /* Local index variables */ diff --git a/test/mf.c b/test/mf.c new file mode 100644 index 0000000..24f3333 --- /dev/null +++ b/test/mf.c @@ -0,0 +1,5386 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Tests for file memory management consist of 3 parts: + * test_mf_eoa_*() tests for file meomory that interact with file allocation + * test_mf_fs_*() tests for file memory that interact with the free-space manager + * test_mf_aggr_*() tests for file memory that interact with the aggregators + * test_mf_align_*() tests for file memory with alignment setting + */ + +#include "h5test.h" + +#define H5MF_PACKAGE +#include "H5MFpkg.h" + +#define H5FS_PACKAGE +#include "H5FSpkg.h" + +#define H5F_PACKAGE +#include "H5Fpkg.h" + +#include "H5FLprivate.h" +#include "H5Iprivate.h" +#include "H5Vprivate.h" + +#define FILENAME_LEN 1024 +#define TEST_FSPACE_CLIENT_ID 2 + +#define TEST_BLOCK_SIZE5 5 +#define TEST_BLOCK_SIZE10 10 +#define TEST_BLOCK_SIZE20 20 +#define TEST_BLOCK_SIZE30 30 +#define TEST_BLOCK_SIZE40 40 +#define TEST_BLOCK_SIZE50 50 +#define TEST_BLOCK_SIZE80 80 +#define TEST_BLOCK_SIZE200 200 +#define TEST_BLOCK_SIZE600 600 +#define TEST_BLOCK_SIZE700 700 +#define TEST_BLOCK_SIZE1034 1034 +#define TEST_BLOCK_SIZE1970 1970 +#define TEST_BLOCK_SIZE2058 2058 +#define TEST_BLOCK_SIZE8000 8000 +#define TEST_BLOCK_SIZE2048 2048 +#define TEST_BLOCK_SIZE1024 1024 + +#define TEST_BLOCK_ADDR70 70 +#define TEST_BLOCK_ADDR100 100 + +#define TEST_ALIGN1024 1024 +#define TEST_ALIGN4096 4096 + +const char *FILENAME[] = { + "mf", + NULL +}; + +typedef enum { + TEST_NORMAL, /* size of aggregator is >= alignment size */ + TEST_AGGR_SMALL, /* size of aggregator is smaller than alignment size */ + TEST_NTESTS /* The number of test types, must be last */ +} test_type_t; + +typedef struct frspace_state_t { + hsize_t tot_space; /* Total amount of space tracked */ + hsize_t tot_sect_count; /* Total # of sections tracked */ + hsize_t serial_sect_count; /* # of serializable sections tracked */ + hsize_t ghost_sect_count; /* # of un-serializable sections tracked */ +} frspace_state_t; + + +static int check_stats(const H5FS_t *, const frspace_state_t *); + +/* + * Verify statistics for the free-space manager + */ +static int +check_stats(const H5FS_t *frsp, const frspace_state_t *state) +{ + H5FS_stat_t frspace_stats; /* Statistics about the heap */ + + /* Get statistics for free-space and verify they are correct */ + if(H5FS_stat_info(frsp, &frspace_stats) < 0) + FAIL_STACK_ERROR + + if(frspace_stats.tot_space != state->tot_space) { + HDfprintf(stdout, "frspace_stats.tot_space = %Hu, state->tot_space = %Zu\n", + frspace_stats.tot_space, state->tot_space); + TEST_ERROR + } /* end if */ + if(frspace_stats.tot_sect_count != state->tot_sect_count) { + HDfprintf(stdout, "frspace_stats.tot_sect_count = %Hu, state->tot_sect_count = %Hu\n", + frspace_stats.tot_sect_count, state->tot_sect_count); + TEST_ERROR + } /* end if */ + if(frspace_stats.serial_sect_count != state->serial_sect_count) { + HDfprintf(stdout, "frspace_stats.serial_sect_count = %Hu, state->serial_sect_count = %Hu\n", + frspace_stats.serial_sect_count, state->serial_sect_count); + TEST_ERROR + } /* end if */ + if(frspace_stats.ghost_sect_count != state->ghost_sect_count) { + HDfprintf(stdout, "frspace_stats.ghost_sect_count = %Hu, state->ghost_sect_count = %Hu\n", + frspace_stats.ghost_sect_count, state->ghost_sect_count); + TEST_ERROR + } /* end if */ + + /* All tests passed */ + return(0); + +error: + return(1); +} /* check_stats() */ + + +/* + * To verify that blocks are allocated from file allocation + * + * Set up: + * Turn off using meta/small data aggregator + * There is nothing in free-space manager + * + * Allocate two blocks which should be from file allocation + */ +static int +test_mf_eoa(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type; + haddr_t addr1, addr2; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + hsize_t ma_size=0; + + TESTING("H5MM_alloc() of file allocation"); + + /* Set the filename to use for this test */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + H5Pset_meta_block_size(fapl_new, (hsize_t)0); + H5Pset_small_data_block_size(fapl_new, (hsize_t)0); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if (new_ma_addr != ma_addr) + TEST_ERROR + + if (addr1 < (haddr_t)file_size) + TEST_ERROR + + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if (new_ma_addr != ma_addr) + TEST_ERROR + + if (addr2 < (haddr_t)file_size) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != (file_size+TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50)) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_eoa() */ + +/* + * To verify that an allocated block from file allocation is shrunk. + * + * Set up: + * Turn off using meta/small data aggregator + * There is nothing in free-space manager + * + * Test 1: Allocate a block of 30 from file allocation + * H5MF_try_shrink() the block by 30 : succeed + * Test 2: Allocate a block of 30 from file allocation + * H5MF_try_shrink() the block by 20 : fail + * Test 3: Allocate a block of 30 from file allocation + * H5MF_try_shrink() the block by 40 : fail + * Test 4: Allocate a block of 30 from file allocation + * H5MF_try_shrink() the block by 20 from the end: succeed + * + */ +static int +test_mf_eoa_shrink(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + htri_t status; + H5FD_mem_t type; + haddr_t addr; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0; + + TESTING("H5MF_try_shrink() of file allocation: test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + H5Pset_meta_block_size(fapl_new, (hsize_t)0); + H5Pset_small_data_block_size(fapl_new, (hsize_t)0); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + if (addr < (haddr_t)file_size) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) TEST_ERROR + if (new_ma_size != ma_size) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != (file_size+TEST_BLOCK_SIZE30)) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + /* should succeed */ + status = H5MF_try_shrink(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)TEST_BLOCK_SIZE30); + if (status <= 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if (new_ma_addr != ma_addr) TEST_ERROR + if (new_ma_size != ma_size) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_try_shrink() of file allocation: test 2"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + if (addr < (haddr_t)file_size) + TEST_ERROR + + /* should not succeed in shrinking */ + status = H5MF_try_shrink(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)TEST_BLOCK_SIZE30-10); + if (status > 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if (new_ma_addr != ma_addr) TEST_ERROR + if (new_ma_size != ma_size) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != (file_size+TEST_BLOCK_SIZE30)) + TEST_ERROR + + PASSED() + + + TESTING("H5MF_try_shrink() of file allocation: test 3"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + /* should not succeed in shrinking */ + status = H5MF_try_shrink(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)TEST_BLOCK_SIZE30+10); + if (status > 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if (new_ma_addr != ma_addr) TEST_ERROR + if (new_ma_size != ma_size) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != (file_size+TEST_BLOCK_SIZE30)) + TEST_ERROR + + PASSED() + + TESTING("H5MF_try_shrink() of file allocation: test 4"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + /* should succeed in shrinking */ + status = H5MF_try_shrink(f, type, H5P_DATASET_XFER_DEFAULT, addr+10, (hsize_t)(TEST_BLOCK_SIZE30-10)); + if (status <= 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if (new_ma_addr != ma_addr) TEST_ERROR + if (new_ma_size != ma_size) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != (file_size+10)) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_eoa_shrink() */ + +/* + * To verify that an allocated block from file allocation is extended. + * + * Set up: + * Turn off using meta/small data aggregator + * There is nothing in free-space manager + * + * Test 1: Allocate a block of 30 + * H5MF_try_extend() the block of size 30 by 50: succeed + * + * Test 2: Allocate a block of 30 + * H5MF_try_extend() the block of size 20 by 50: fail + */ +static int +test_mf_eoa_extend(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* File size */ + H5FD_mem_t type; + haddr_t addr; + htri_t extended; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0; + + TESTING("H5MF_try_extend() of file allocation: test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + H5Pset_meta_block_size(fapl_new, (hsize_t)0); + H5Pset_small_data_block_size(fapl_new, (hsize_t)0); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + if (addr < (haddr_t)file_size) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != (file_size+TEST_BLOCK_SIZE30)) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* should succeed */ + extended = H5MF_try_extend(f, H5P_DATASET_XFER_DEFAULT, type, (haddr_t)addr, (hsize_t)TEST_BLOCK_SIZE30, (hsize_t)TEST_BLOCK_SIZE50); + + if(extended <= 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != (file_size+TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50)) + TEST_ERROR + + PASSED() + + TESTING("H5MF_try_extend() of file allocation: test 2"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + if (addr < (haddr_t)file_size) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) + TEST_ERROR + + extended = H5MF_try_extend(f, H5P_DATASET_XFER_DEFAULT, type, (haddr_t)addr, (hsize_t)(TEST_BLOCK_SIZE30-10), (hsize_t)(TEST_BLOCK_SIZE50)); + + /* should not succeed */ + if(extended > 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size+TEST_BLOCK_SIZE30) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_eoa_extend() */ + +/* + * To verify that the free-space manager is started up via H5MF_alloc_start() + * + * Set up: + * Turn off using meta/small data aggregator + */ +static int +test_mf_fs_start(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type; + frspace_state_t state; + + + TESTING("H5MF_alloc_start() of free-space manager"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + H5Pset_meta_block_size(fapl_new, (hsize_t)0); + H5Pset_small_data_block_size(fapl_new, (hsize_t)0); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up free-space manager */ + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_start() */ + + +/* + * To verify that a block is allocated/freed from/to the free-space manager + * + * Set up: + * Turn off using meta/small data aggregator + * + * Test 1: + * Add section A to free-space manager (addr=70, size=30) + * Allocate a block of size=30 + * The returned space's address should be same as section A's address + * Deallocate the block which will be returned to the free-space manager + * Test 2: + * Add section A to free-space manager (addr=70, size=30) + * Allocate a block of size=20 + * The returned space's address should be same as section A's address + * There should still be space of 10 left in the free-space manager + * Deallocate the block which will be returned to free-space manager + * Test 3: + * Add section A to free-space manager (addr=70, size=30) + * Allocate a block of size=40 + * The free-space manager is unable to fulfill the request + * The block is allocated from file allocation + * Deallocate the block which will be returned to free-space manager + * (the space is shrunk and freed since it is at end of file) + */ +static int +test_mf_fs_alloc_free(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type; + H5MF_free_section_t *sect_node = NULL; + haddr_t addr; + frspace_state_t state; + H5MF_sect_ud_t udata; + H5FS_section_info_t *node; + htri_t node_found = FALSE; + + TESTING("H5MF_alloc()/H5MF_xfree() of free-space manager:test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + H5Pset_meta_block_size(fapl_new, (hsize_t)0); + H5Pset_small_data_block_size(fapl_new, (hsize_t)0); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR70, (hsize_t)TEST_BLOCK_SIZE30); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* Add section A to free-space manager */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_BLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Allocate a block of 30 */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is section A in free-space */ + if (addr != TEST_BLOCK_ADDR70) + TEST_ERROR + + state.tot_space -= TEST_BLOCK_SIZE30; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free the block to free-space */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)TEST_BLOCK_SIZE30); + + state.tot_space += TEST_BLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Remove section A from free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], + (hsize_t)TEST_BLOCK_SIZE30, (H5FS_section_info_t **)&node)) < 0) + + /* Free the free-space section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_alloc()/H5MF_xfree() of free-space manager:test 2"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR70, (hsize_t)TEST_BLOCK_SIZE30); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* Add section A to free-space manager */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_BLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Allocate a block of 20 */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)(TEST_BLOCK_SIZE20)); + + /* Verify that the allocated block is section A in free-space manager */ + if (addr != TEST_BLOCK_ADDR70) + TEST_ERROR + + /* should still have 1 section of size 10 left in free-space manager */ + state.tot_space -= (TEST_BLOCK_SIZE20); + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free the block to free-space manager */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)(TEST_BLOCK_SIZE20)); + + /* Still 1 section in free-space because of merging */ + state.tot_space += TEST_BLOCK_SIZE20; + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Remove section A from free-space manager */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], + (hsize_t)TEST_BLOCK_SIZE30, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + /* Free the free-space section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_alloc()/H5MF_xfree() of free-space manager:test 3"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR70, (hsize_t)TEST_BLOCK_SIZE30); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* Add section A to free-space manager */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_BLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* + * Allocate a block of 40. + * Since free-space manager cannot fulfull the request, + * the block is obtained from file allocation + */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)(TEST_BLOCK_SIZE40)); + + /* Verify that the allocated block is not section A in free-space */ + if (addr == TEST_BLOCK_ADDR70) + TEST_ERROR + + /* free-space info should be the same */ + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Remove section A from free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], + (hsize_t)TEST_BLOCK_SIZE30, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + /* Free the free-space section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free the block of size 40 to free-space */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)(TEST_BLOCK_SIZE40)); + + /* + * Free-space info is the same. + * The block is returned to free-space. + * It is shrunk and freed because it is at end of file. + */ + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (file_size != file_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_alloc_free() */ + + +/* + * To verify that a block allocated from the free-space manager can be extended + * + * Set up: + * Turn off using meta/small data aggregator + * + * Test 1: + * Add section A to free-space manager: addr=70, size=30 + * Allocate a block of size 30 from free-space manager + * Add section B to free-space manager: addr=100, size=50 + * Try to extend the allocated block by requested-size=50 + * Succeed: section A adjoins section B (70+30=100 which is section B's address) and + * requested-size (50) is equal to the size of section B + * Test 2: + * Add section A to free-space manager: addr=70, size=30 + * Allocate a block of size 30 from free-space manager + * Add section B to free-space manager: addr=100, size=50 + * Try to extend the allocated block by requested-size=60 + * Fail: section A adjoins section B (70+30=100 which is section B's address) but + * requested-size (60) > size of section B (50) + * + * Test 3: + * Add section A to free-space manager: addr=70, size=30 + * Allocate a block of size 30 from free-space manager + * Add section B to free-space manager: addr=100, size=50 + * Try to extend the allocated block by requested-size=40 + * Succeed: section A adjoins section B (70+30=100 which is section B's address) and + * requested-size (40) < size of section B (50), therefore, + * a section of 10 is left in the free-space manager + * Test 4: + * Add section A to free-space manager: addr=70, size=20 + * Allocate a block of size 20 from free-space manager + * Add section B to free-space manager: addr=100, size=50 + * Try to extend the allocated block by 50 from the free-space_manager: + * Fail: section A does not adjoin section B (70+20 != address of section B) even though + * the requested-size (50) equal to size of section B (50) + */ +static int +test_mf_fs_extend(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type; + H5MF_free_section_t *sect_node1 = NULL, *sect_node2=NULL; + haddr_t addr; + frspace_state_t state; /* State of free space*/ + H5MF_sect_ud_t udata; + H5FS_section_info_t *node; + htri_t node_found = FALSE; + htri_t extended; + + TESTING("H5MF_try_extend() of free-space manager:test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + H5Pset_meta_block_size(fapl_new, (hsize_t)0); + H5Pset_small_data_block_size(fapl_new, (hsize_t)0); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node1 = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR70, (hsize_t)TEST_BLOCK_SIZE30); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* Add section A to free-space manager */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node1, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_BLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Allocate a block of 30 */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is section A in free-space manager */ + if (addr != TEST_BLOCK_ADDR70) + TEST_ERROR + + state.tot_space -= TEST_BLOCK_SIZE30; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Create section B */ + sect_node2 = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR100, (hsize_t)TEST_BLOCK_SIZE50); + + /* Add section B to free-space manager */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node2, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + state.tot_space += TEST_BLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Try to extend the allocated block */ + extended = H5MF_try_extend(f, H5P_DATASET_XFER_DEFAULT, type, (haddr_t)TEST_BLOCK_ADDR70, (hsize_t)TEST_BLOCK_SIZE30, (hsize_t)TEST_BLOCK_SIZE50); + + /* should succeed */ + if(extended <= 0) + TEST_ERROR + + /* Section B is removed from free-space manager */ + state.tot_space -= TEST_BLOCK_SIZE50; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free the extended block to free-space manager */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)(TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50)); + + /* Verify that the extended block is back into free-space */ + state.tot_space += TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50; + state.tot_sect_count = 1; + state.serial_sect_count = 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Remove the extended block */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], + (hsize_t)(TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50), (H5FS_section_info_t **)&node)) < 0) + TEST_ERROR + + /* Remove the free-space section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_try_extend() of free-space manager:test 2"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node1 = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR70, (hsize_t)TEST_BLOCK_SIZE30); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* Add section A to free-space */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node1, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_BLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Allocate a block of 30 */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is section A in free-space manager */ + if (addr != TEST_BLOCK_ADDR70) + TEST_ERROR + + state.tot_space -= TEST_BLOCK_SIZE30; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Create section B */ + sect_node2 = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR100, (hsize_t)TEST_BLOCK_SIZE50); + + /* Add section B to free-space manager */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node2, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + state.tot_space += TEST_BLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Try to extend the allocated block */ + extended = H5MF_try_extend(f, H5P_DATASET_XFER_DEFAULT, type, (haddr_t)TEST_BLOCK_ADDR70, (hsize_t)TEST_BLOCK_SIZE30, (hsize_t)(TEST_BLOCK_SIZE50+10)); + + /* Should not be able to extend the allocated block */ + if(extended) + TEST_ERROR + + /* free-space info should remain the same */ + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free the allocated block A to free-space */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)TEST_BLOCK_SIZE30); + + /* the returned section A is merged with section B in free-space */ + /* rest of the info remains the same */ + state.tot_space += TEST_BLOCK_SIZE30; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Remove the merged sections A & B from free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], + (hsize_t)(TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50), (H5FS_section_info_t **)&node)) < 0) + TEST_ERROR + + /* Remove the free-space section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_try_extend() of free-space manager:test 3"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node1 = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR70, (hsize_t)TEST_BLOCK_SIZE30); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* Add section A to free-space */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node1, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_BLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Allocate a block of 30 */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is section A in free-space manager */ + if (addr != TEST_BLOCK_ADDR70) + TEST_ERROR + + state.tot_space -= TEST_BLOCK_SIZE30; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Create section B */ + sect_node2 = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR100, (hsize_t)TEST_BLOCK_SIZE50); + + /* Add section B to free-space manager */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node2, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + state.tot_space += TEST_BLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Try to extend the allocated block */ + extended = H5MF_try_extend(f, H5P_DATASET_XFER_DEFAULT, type, (haddr_t)TEST_BLOCK_ADDR70, (hsize_t)TEST_BLOCK_SIZE30, (hsize_t)(TEST_BLOCK_SIZE40)); + + /* Should succeed in extending the allocated block */ + if(extended <=0) + TEST_ERROR + + /* Should have 1 section of size=10 left in free-space manager */ + state.tot_space -= (TEST_BLOCK_SIZE40); + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free the extended block */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)(TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE40)); + + /* rest info is same, the extended section returned is merged with the section in free-space */ + state.tot_space += (TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE40); + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Remove the merged sections A & B from free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], + (hsize_t)(TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50), (H5FS_section_info_t **)&node)) < 0) + TEST_ERROR + + /* Remove the free-space section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_try_extend() of free-space manager:test 4"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node1 = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR70, (hsize_t)(TEST_BLOCK_SIZE30-10)); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* Add section A of size=20 to free-space */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node1, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += (TEST_BLOCK_SIZE30-10); + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Allocate a block of size=20 */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)(TEST_BLOCK_SIZE30-10)); + + /* Verify that the allocated block is section A in free-space manager */ + if (addr != TEST_BLOCK_ADDR70) + TEST_ERROR + + state.tot_space -= (TEST_BLOCK_SIZE30-10); + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Create section B */ + sect_node2 = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR100, (hsize_t)TEST_BLOCK_SIZE50); + + /* Add section B to free-space manager */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node2, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + state.tot_space += TEST_BLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Try to extend the allocated block */ + extended = H5MF_try_extend(f, H5P_DATASET_XFER_DEFAULT, type, (haddr_t)TEST_BLOCK_ADDR70, (hsize_t)(TEST_BLOCK_SIZE30-10), (hsize_t)TEST_BLOCK_SIZE50); + + /* Should not succeed in extending the allocated block */ + if(extended) + TEST_ERROR + + /* Free-space info should be the same */ + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free the allocated block */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)(TEST_BLOCK_SIZE30-10)); + + state.tot_space += (TEST_BLOCK_SIZE30-10); + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Remove section A from free-space manger */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], + (hsize_t)(TEST_BLOCK_SIZE30-10), (H5FS_section_info_t **)&node)) < 0) + TEST_ERROR + + /* Remove the free-space section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* Remove section B from free-space manager */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], + (hsize_t)TEST_BLOCK_SIZE50, (H5FS_section_info_t **)&node)) < 0) + TEST_ERROR + + /* Remove the free-space section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_extend() */ + +/* + * To verify that an aggregator is absorbed into a section. + * + * Test 1: To aborb the aggregator onto the beginning of the section + * Allocate block A from meta_aggr + * Create a free-space section node with an address that adjoins + * the end of meta_aggr and a size to make the aggregator + * get absorbed into the section. + * The adding of the section to free-space will call H5MF_aggr_absorb(), + * which will absorb meta_aggr to the section: + * section size + remaining size of aggregator is > aggr->alloc_size, + * section is allowed to absorb an aggregator (allow_sect_absorb is true) + * + * Test 2: To absorb the aggregator onto the end of the section + * Allocate block A from meta_aggr + * Allocate block B from sdata_aggr + * Create a free-space section node with an address that adjoins + * the beginning of meta_aggr and a size to make the + * aggregator get absorbed into the section. + * The adding of the section to free-space will call H5MF_aggr_absorb(), + * which will absorb meta_aggr to the section: + * section size + remaining size of aggregator is > aggr->alloc_size, + * section is allowed to absorb an aggregator (allow_sect_absorb is true) + */ +static int +test_mf_fs_absorb(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FD_mem_t type, stype; + haddr_t addr, saddr; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0; + H5MF_free_section_t *sect_node=NULL; + H5MF_sect_ud_t udata; + htri_t node_found=FALSE; + H5FS_section_info_t *node; + + TESTING("A free-space section absorbs an aggregator: test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Allocate a section from meta_aggr */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + /* Add a section to free-space that adjoins end of the aggregator */ + sect_node = H5MF_sect_simple_new((haddr_t)(ma_addr+ma_size), (hsize_t)TEST_BLOCK_SIZE2048); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* When adding, meta_aggr is absorbed onto the beginning of the section */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + /* Verify that the section did absorb the aggregator */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], + (hsize_t)TEST_BLOCK_SIZE2048, (H5FS_section_info_t **)&node)) < 0) + TEST_ERROR + + if (node->addr != ma_addr) TEST_ERROR + if (node->size != (ma_size + TEST_BLOCK_SIZE2048)) TEST_ERROR + + /* Remove the free-space section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* Restore info for aggregator */ + f->shared->meta_aggr.addr = ma_addr; + f->shared->meta_aggr.size = ma_size; + + /* Remove section from meta_aggr */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)TEST_BLOCK_SIZE30); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("A free-space section absorbs an aggregator: test 2"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Allocate a section from meta_aggr */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + /* Allocate a section from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + /* Add a section to free-space that adjoins the beginning of meta_aggr */ + sect_node = H5MF_sect_simple_new((haddr_t)addr, (hsize_t)TEST_BLOCK_SIZE30); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* When adding, meta_aggr is absorbed onto the end of the section */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + /* Verify that the section did absorb the aggregator */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], + (hsize_t)(ma_size+TEST_BLOCK_SIZE30), (H5FS_section_info_t **)&node)) < 0) + TEST_ERROR + + if ((node->addr + TEST_BLOCK_SIZE30) != ma_addr) TEST_ERROR + if (node->size != (ma_size + TEST_BLOCK_SIZE30)) TEST_ERROR + + /* free the free-space section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* restore info to meta_aggr */ + f->shared->meta_aggr.addr = ma_addr; + f->shared->meta_aggr.size = ma_size; + + /* Remove section from meta_aggr */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)TEST_BLOCK_SIZE30); + /* Remove section from sdata_aggr */ + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr, (hsize_t)TEST_BLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_absorb() */ + +/* + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * The first block of 30 is allocated from meta_aggr + * There is space of 2018 left in meta_aggr + * + * Allocate second block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr + * Result: + * The second block of 50 is allocated from meta_aggr + * There is space of 1968 left in meta_aggr + */ +static int +test_mf_aggr_alloc1(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type; + haddr_t addr1, addr2; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0; + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate second block from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr2+TEST_BLOCK_SIZE50) != ma_addr) + TEST_ERROR + if (ma_size != (TEST_BLOCK_SIZE2048 - (TEST_BLOCK_SIZE30 + TEST_BLOCK_SIZE50))) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != (file_size+TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50)) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Free the two blocks */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc1() */ + +/* + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * There is space of 2018 left in meta_aggr + * + * Allocate second block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr + * Result: + * The second block of 50 is allocated from what is left in meta_aggr + * There is space of 1968 left in meta_aggr + * + * Allocate third block (2058) from meta_aggr: + * request-size is > what is left in meta_aggr and is >= meta_aggr->alloc_size + * meta_aggr is at EOA + * Result: + * A block of request-size is extended via file allocation and is merged with meta_aggr + * The block of 2058 is allocated out of meta_aggr + * There is space of 1968 left in meta_aggr + */ +static int +test_mf_aggr_alloc2(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type; + haddr_t addr1, addr2, addr3; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0; + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 2"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file */ + if((file_size= h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr2+TEST_BLOCK_SIZE50) != ma_addr) + TEST_ERROR + + if (ma_size != (TEST_BLOCK_SIZE2048 - (TEST_BLOCK_SIZE30 + TEST_BLOCK_SIZE50))) + TEST_ERROR + + addr3 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE2058); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr3+TEST_BLOCK_SIZE2058) != ma_addr) + TEST_ERROR + + if (ma_size != (TEST_BLOCK_SIZE2048 - (TEST_BLOCK_SIZE30 + TEST_BLOCK_SIZE50))) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + /* Unused space is freed from the end of the file */ + if (new_file_size != (file_size+TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50+TEST_BLOCK_SIZE2058)) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50+TEST_BLOCK_SIZE2058); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc2() */ + +/* + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr : (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * There is space of 2018 left in meta_aggr + * + * Allocate second block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr + * Result: + * The second block of 50 is allocated from what is left in meta_aggr + * There is space of 1968 left in meta_aggr + * + * Allocate first block (30) from sdata_aggr: (nothing in sdata_aggr) + * request-size is > what is left in other_aggr and is < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * There is space of 2018 left in sdata_aggr + * + * Allocate the third block (2058) from meta_aggr: + * request-size is > what is left in meta_aggr and >= meta_aggr->alloc_size + * sdata_aggr is at EOA but has not used up more than sdata_aggr->alloc_size + * Result: A block of request-size is obtained via file allocation + * The new block's address is returned + * Nothing is changed in meta_aggr and sdata_aggr + * + * Allocate fourth block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * The fourth block of 50 is allocated from what is left in meta_aggr + * There is space of 1968 left in meta_aggr + */ +static int +test_mf_aggr_alloc3(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3, addr4, saddr1; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0; + haddr_t sdata_addr=HADDR_UNDEF; + hsize_t sdata_size=0; + + TESTING("H5MF_alloc() of meta/sdata aggregator: test 3"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate second block from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr2+TEST_BLOCK_SIZE50) != ma_addr) + TEST_ERROR + if (ma_size != (TEST_BLOCK_SIZE2048 - (TEST_BLOCK_SIZE30 + TEST_BLOCK_SIZE50))) + TEST_ERROR + + /* Allocate first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr1+TEST_BLOCK_SIZE30) != sdata_addr) + TEST_ERROR + if (sdata_size != (TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE30)) TEST_ERROR + + /* Allocate third block, which is from file allocation not from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)(TEST_BLOCK_SIZE2058)); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + /* info for meta_aggr shouldn't be changed */ + if (addr3 != (sdata_addr+sdata_size)) TEST_ERROR + if ((addr3+TEST_BLOCK_SIZE2058) == new_ma_addr) TEST_ERROR + if ((new_ma_addr != ma_addr) || (new_ma_size != ma_size)) TEST_ERROR + + /* Allocate fourth block, which should be from meta_aggr */ + addr4 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr4+TEST_BLOCK_SIZE50) != ma_addr) + TEST_ERROR + if (ma_size != (TEST_BLOCK_SIZE2048 - (TEST_BLOCK_SIZE30 + TEST_BLOCK_SIZE50 + TEST_BLOCK_SIZE50))) + TEST_ERROR + + /* Free all the allocated blocks */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr3, (hsize_t)TEST_BLOCK_SIZE2058); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr4, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr1, (hsize_t)TEST_BLOCK_SIZE30); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc3() */ + + +/* + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * There is space of 2018 left in meta_aggr + * The first block of 30 is allocated from there + * + * Allocate first block (30) from sdata_aggr: (nothing in sdata_aggr) + * request-size is > what is left in sdata_aggr and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * + * Allocate the second block (2018) from sdata_aggr: + * request-size is <= what is left in sdata_aggr and < sdata_aggr->alloc_size + * request-size is < sdata_aggr->alloc_size + * Result: + * The block is allocated from what is left in sdata_aggr (all used up) + * + * Allocate third block (50) from sdata_aggr : + * request-size is > what is left in sdata_aggr and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is extended via file allocation + * The third block of 50 is allocated from there + * There is space of 1998 left in the sdata_aggr + * + * Allocate second block (2058) from meta_aggr: + * request-size is > what is left in meta_aggr and >= meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * unused spaced in sdata_aggr is freed to free-space and is shrunk + * sdata_aggr is reset to 0 + * A block of request-size is obtained via file allocation + * The new block's address is returned + * The block does not adjoin meta_aggr + * meta_aggr's info is unchanged + */ +static int +test_mf_aggr_alloc4(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* File size */ + H5FD_mem_t type, stype; + haddr_t addr1, addr2, saddr1, saddr2, saddr3; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0, sdata_size=0; + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 4"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr1+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + if (ma_size != (TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE30)) + TEST_ERROR + + /* Allocate first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr1+TEST_BLOCK_SIZE30) != sdata_addr) + TEST_ERROR + + /* Allocate second block from sdata_aggr */ + saddr2 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)(TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE30)); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if (saddr2+(TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE30) != sdata_addr) + TEST_ERROR + + /* Allocate third block from sdata_aggr */ + saddr3 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + + if ((saddr3+TEST_BLOCK_SIZE50) != sdata_addr) + TEST_ERROR + if(sdata_size != (TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE50)) + TEST_ERROR + + /* Allocate second block of 2058, which is from file allocation, not from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE2058); + + if (addr2 != sdata_addr) + TEST_ERROR + + /* sdata_aggr is reset 0 */ + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((sdata_addr != 0) && (sdata_size != 0)) + TEST_ERROR + + /* info is unchanged in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if ((new_ma_addr != ma_addr) && (new_ma_size != ma_size)) + TEST_ERROR + + /* Free all the allocated blocks */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE2058); + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr2, (hsize_t)TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE30); + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr3, (hsize_t)TEST_BLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc4() */ + +/* + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocate from there + * + * Allocate second block (50) from meta_aggr: + * request-size is < what is left in meta_aggr + * Result: + * The second block of 50 is allocated from what is left there + * There is space of 1968 left in the meta_aggr + * + * Allocate third block (1970) from meta_aggr: + * request-size is > what is left in meta_aggr and is < meta_aggr->alloc_size + * Result: A block of meta_aggr->alloc_size is extended via file allocation and is absorbed into the meta_aggr + * The block of 1970 is allocated from there + * There is space of 2046 left in meta_aggr + * + */ +static int +test_mf_aggr_alloc5(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* File size */ + H5FD_mem_t type; + haddr_t addr1, addr2, addr3; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0; + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 5"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate second block from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if (addr2+TEST_BLOCK_SIZE50 != ma_addr) + TEST_ERROR + if (ma_size != (TEST_BLOCK_SIZE2048 - (TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50))) + TEST_ERROR + + /* Allocate third block from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE1970); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if (addr3 != ma_addr) TEST_ERROR + if ((addr3+TEST_BLOCK_SIZE1970) != new_ma_addr) TEST_ERROR + if (new_ma_size != (TEST_BLOCK_SIZE2048 - (TEST_BLOCK_SIZE1970 - ma_size))) + TEST_ERROR + + /* Free all the allocated blocks */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr3, (hsize_t)TEST_BLOCK_SIZE1970); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc5() */ + +/* + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * + * Allocate second block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr + * Result: + * The second block of 50 is allocated from what is left in meta_aggr + * There is space of 1968 left in meta_aggr + * + * Allocate first block (30) from sdata_aggr: (nothing in sdata_aggr) + * request-size is > what is left in sdata_aggr and is < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * There is space of 2018 left in sdata_aggr + * + * Allocate third block (1970) from meta_aggr: + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * sdata_aggr is at EOA but has not used up more than sdata_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation. + * The block does not adjoin meta_aggr + * sdata_aggr is untouched + * meta_aggr's unused space of [880, 1968] is freed to free-space + * meta_aggr is updated to point to the new block + */ +static int +test_mf_aggr_alloc6(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3, saddr1; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0, sdata_size=0; + frspace_state_t state; + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 6"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate second block from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if (addr2+TEST_BLOCK_SIZE50 != ma_addr) + TEST_ERROR + if (ma_size != (TEST_BLOCK_SIZE2048 - (TEST_BLOCK_SIZE30 + TEST_BLOCK_SIZE50))) + TEST_ERROR + + /* Allocate first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr1+TEST_BLOCK_SIZE30) != sdata_addr) TEST_ERROR + if (sdata_size != (TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE30)) TEST_ERROR + + /* Allocate third block from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE1970); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if ((addr3+TEST_BLOCK_SIZE1970) != new_ma_addr) TEST_ERROR + if (addr3 != (sdata_addr+sdata_size)) TEST_ERROR + + if ((ma_addr+TEST_BLOCK_SIZE1970) == new_ma_addr) TEST_ERROR + if (new_ma_size != (TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE1970)) + TEST_ERROR + + /* Verify that meta_aggr's unused space of 1968 is freed to free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += (TEST_BLOCK_SIZE2048 - (TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50)); + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free all the allocated blocks */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr3, (hsize_t)TEST_BLOCK_SIZE1970); + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr1, (hsize_t)TEST_BLOCK_SIZE30); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc6() */ + +/* + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in meta_aggr) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * + * Allocate second block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr + * Result: + * The second block of 50 is allocated from what is left in the aggregator + * There is space of 1968 left in the meta_aggr + * + * Allocate first block (30) from sdata_aggr: (nothing in sdata_aggr) + * request-size is > what is left in sdata_aggr->size and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocate from there + * + * Allocate second block (2018) from sdata_aggr: + * request-size is <= what is left in sdata_aggr and is < sdata_aggr->alloc_size + * Result: + * The second block of 2018 is allocated from what is left in sdata_aggr (all used up) + * + * Allocate third block (50) from sdata_aggr: + * request-size is > what is left in sdata_aggr and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is extended via file allocation + * The third block of 50 is allocated from there + * + * Allocate third block (1970) from meta_aggr: + * request-size is > what is left in meta_aggr and is < meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * unused space in sdata_aggr is freed to free-space and is shrunk + * sdata_aggr is reset to 0 + * A block of meta_aggr->alloc_size is obtained via file allocation + * The block does not adjoin meta_aggr + * meta_aggr's unused space of [880, 1968] is freed to free-space + * meta_aggr is updated to point to the new block + */ +static int +test_mf_aggr_alloc7(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t empty_size, file_size; + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3, saddr1, saddr2, saddr3; + haddr_t ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, sdata_size=0; + frspace_state_t state; + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 7"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((empty_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate the first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate the second block from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if (addr2+TEST_BLOCK_SIZE50 != ma_addr) + TEST_ERROR + if (ma_size != (TEST_BLOCK_SIZE2048 - (TEST_BLOCK_SIZE30 + TEST_BLOCK_SIZE50))) + TEST_ERROR + + /* Allocate the first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr1+TEST_BLOCK_SIZE30) != sdata_addr) + TEST_ERROR + + /* Allocate the second block from sdata_aggr */ + saddr2 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr2+(TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE30)) != sdata_addr) + TEST_ERROR + if (sdata_size != 0) TEST_ERROR + + /* Allocate the third block from sdata_aggr */ + saddr3 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr3+TEST_BLOCK_SIZE50) != sdata_addr) + TEST_ERROR + if (sdata_size != (TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE50)) + TEST_ERROR + + /* Allocate the third block from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE1970); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if (addr3 != sdata_addr) TEST_ERROR + if ((addr3 + TEST_BLOCK_SIZE1970) != ma_addr) TEST_ERROR + if (ma_size != (TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE1970)) TEST_ERROR + + /* sdata_aggr info is reset to 0 */ + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if (sdata_addr != 0) TEST_ERROR + if (sdata_size != 0) TEST_ERROR + + /* Verify that meta_aggr's unused space of 1968 is freed to free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += (TEST_BLOCK_SIZE2048 - (TEST_BLOCK_SIZE30 + TEST_BLOCK_SIZE50)); + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free all the allocated blocks */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr3, (hsize_t)TEST_BLOCK_SIZE1970); + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr2, (hsize_t)(TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE30)); + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr3, (hsize_t)TEST_BLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (file_size != empty_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc7() */ + +/* + * To verify that a block can be extended from the aggregator + * + * Test 1: Allocate block A from meta_aggr which is at end of file + * Try to extend a block which adjoins the aggregator + * H5MF_try_extend() succeeds: meta_aggr is extended by extended-request and meta_aggr's info is updated + * + * Test 2: Allocate block A from meta_aggr + * Allocate block B from sdata_aggr so that meta_aggr is not at end of file + * Try to extend a block which adjoins meta_aggr and meta_aggr can fulfill the extended-request + * H5MF_try_extend() succeeds: the block is extended into the aggregator + * + * Test 3: Allocate block A from meta_aggr + * Allocate block B from sdata_aggr so that meta_aggr is not at end of file + * Try to extend a block which adjoins meta_aggr but meta_aggr cannot fulfill the extended-request + * H5MF_try_extend() fails + */ +static int +test_mf_aggr_extend(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t empty_size; + H5FD_mem_t type, stype; + haddr_t new_addr, addr, saddr; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0, sdata_size=0; + htri_t extended; + + TESTING("H5MF_try_extend() of meta/sdata aggregator: test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((empty_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate the first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Adjust meta_aggr's info info for testing */ + f->shared->meta_aggr.addr = addr; + f->shared->meta_aggr.size = f->shared->meta_aggr.alloc_size; + + new_addr = addr - 10; + + /* Try to extend the block */ + extended = H5MF_try_extend(f, H5P_DATASET_XFER_DEFAULT, type, (haddr_t)new_addr, (hsize_t)10, (hsize_t)(TEST_BLOCK_SIZE50)); + + /* should succeed */ + if(!extended) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if (new_ma_addr != (addr+TEST_BLOCK_SIZE50)) + TEST_ERROR + if (new_ma_size != f->shared->meta_aggr.alloc_size) TEST_ERROR + + /* Restore info for meta_aggr */ + f->shared->meta_aggr.addr = ma_addr; + f->shared->meta_aggr.size = ma_size; + + /* Free the allocated blocks */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, (ma_addr+ma_size), (hsize_t)TEST_BLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("H5MF_try_extend() of meta/sdata aggregator: test 2"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate the first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate the first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr+TEST_BLOCK_SIZE50) != sdata_addr) + TEST_ERROR + + /* Adjust meta_aggr's info info for testing */ + f->shared->meta_aggr.addr = addr; + f->shared->meta_aggr.size = f->shared->meta_aggr.alloc_size; + + new_addr = addr - 10; + + /* should be able to fulfill request from the aggreqator itself */ + extended = H5MF_try_extend(f, H5P_DATASET_XFER_DEFAULT, type, (haddr_t)new_addr, (hsize_t)10, (hsize_t)(TEST_BLOCK_SIZE50)); + + if(!extended) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if (new_ma_addr != (addr+TEST_BLOCK_SIZE50)) + TEST_ERROR + if (new_ma_size != (f->shared->meta_aggr.alloc_size-TEST_BLOCK_SIZE50)) + TEST_ERROR + + /* Restore info for meta_aggr */ + f->shared->meta_aggr.addr = ma_addr; + f->shared->meta_aggr.size = ma_size; + + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr, (hsize_t)TEST_BLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("H5MF_try_extend() of meta/sdata aggregator: test 3"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr+TEST_BLOCK_SIZE50) != sdata_addr) + TEST_ERROR + + /* Adjust meta_aggr's info info for testing */ + f->shared->meta_aggr.addr = addr; + f->shared->meta_aggr.size = 0; + + new_addr = addr - 10; + + /* unable to fulfill request from the aggreqator itself */ + extended = H5MF_try_extend(f, H5P_DATASET_XFER_DEFAULT, type, (haddr_t)new_addr, (hsize_t)10, (hsize_t)(TEST_BLOCK_SIZE50)); + + if(extended) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if (new_ma_addr != addr) TEST_ERROR + if (new_ma_size != 0) TEST_ERROR + + /* restore info for meta_aggr */ + f->shared->meta_aggr.addr = ma_addr; + f->shared->meta_aggr.size = ma_size; + + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr, (hsize_t)TEST_BLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_extend() */ + +/* + * To verify that a block is absorbed into an aggregator + * + * MF_try_shrink() only allows blocks to be absorbed into an aggregator + * + * Test 1: H5MF_alloc() block A from meta_aggr + * H5MF_try_shrink() block A should merge it back into meta_aggr + * since block A adjoins the beginning of meta_aggr + * + * Test 2: H5MF_alloc() block A from meta_aggr + * H5MF_alloc() block B from sdata_aggr + * H5MF_try_shrink() block B should merge it onto the end of meta_aggr + * because H5F_FS_MERGE_METADATA|H5F_FS_MERGE_RAWDATA is on for + * sec2 driver's FLMAP_SINGLE + * + * Test 3: H5MF_alloc() block A from meta_aggr + * H5MF_alloc() block B from meta_aggr + * H5MF_alloc() block C from meta_aggr + * H5MF_try_shrink() block B should fail since it does not adjoin the + * beginning nor the end of meta_aggr + */ +static int +test_mf_aggr_absorb(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t empty_size; + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3, saddr1; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + haddr_t sdata_addr=HADDR_UNDEF, new_sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0; + hsize_t sdata_size=0, new_sdata_size=0; + htri_t status; + + TESTING("H5MF_try_shrink() of meta/sdata aggregator: test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((empty_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate block A from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + ma_addr = new_ma_addr - TEST_BLOCK_SIZE30; + + if ((addr1+TEST_BLOCK_SIZE30) != new_ma_addr) + TEST_ERROR + + /* should succeed */ + if ((status = H5MF_try_shrink(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30)) <= 0) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if (new_ma_addr != ma_addr) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("H5MF_try_shrink() of meta/sdata aggregator: test 2"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate block A from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr1+TEST_BLOCK_SIZE30) != ma_addr) TEST_ERROR + if (ma_size != (TEST_BLOCK_SIZE2048 - TEST_BLOCK_SIZE30)) TEST_ERROR + + /* Allocate block B from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + + /* should succeed */ + if ((status = H5MF_try_shrink(f, stype, H5P_DATASET_XFER_DEFAULT, saddr1, (hsize_t)TEST_BLOCK_SIZE50)) <= 0) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &new_sdata_addr, &new_sdata_size); + if (new_sdata_addr != sdata_addr) TEST_ERROR + if (new_sdata_size != sdata_size) TEST_ERROR + + /* meta_aggr info should be updated because the block is absorbed into the meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) TEST_ERROR + if (new_ma_size != (ma_size+TEST_BLOCK_SIZE50)) TEST_ERROR + + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("H5MF_try_shrink() of meta/sdata aggregator: test 3"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate block A from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr1+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate block B from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr2+TEST_BLOCK_SIZE50) != ma_addr) + TEST_ERROR + + /* Allocate block C from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)(TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50)); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr3+TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50) != ma_addr) + TEST_ERROR + + /* should not succeed */ + if ((status = H5MF_try_shrink(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE50)) > 0) + TEST_ERROR + + /* aggregator info should be the same as before */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) TEST_ERROR + + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr3, (hsize_t)(TEST_BLOCK_SIZE30+TEST_BLOCK_SIZE50)); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_absorb() */ + +/* + * To verify that a block allocated from file allocation is aligned, can be shrunk and extended + * + * Alignment = 1024 or 4096 + * + * Test 1: + * Turn off using meta data aggregator + * Allocate a block of 30 which should be from file allocation + * Result: + * The return address should be aligned + * A fragment [800, 224] or [800, 3296] is freed to free-space + * EOA is 1054 or 4126 + * + * Allocate a block of 50 which should be from file allocation + * Result: + * The return address should be aligned + * A fragment [1054, 994] or [4126, 4066] is freed to free-space + * EOA is 2098 or 8242 + * Test 2: + * Turn off using meta data aggregator + * Allocate a block which should be from file allocation + * The return address should be aligned + * H5MF_try_shrink() the block with aligned address should succeed + * + * Test 3: + * Turn off using meta data aggregator + * Allocate a block which should be from file allocation + * The return address should be aligned + * H5MF_try_extend() the block with aligned address should succeed + */ +static int +test_mf_align_eoa(hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl1; + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; + H5FD_mem_t type; + haddr_t addr1, addr2; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0; + htri_t status, extended; + frspace_state_t state; + hsize_t alignment=0, mis_align=0, tmp=0, accum=0; + + TESTING("H5MM_alloc() of file allocation with alignment: test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Turn off using meta/small data aggregator */ + if((fapl1 = H5Pcopy(new_fapl)) < 0) TEST_ERROR + + H5Pset_meta_block_size(fapl1, (hsize_t)0); + H5Pset_small_data_block_size(fapl1, (hsize_t)0); + + /* Create the file to work on (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(fapl1, NULL, &alignment) < 0) + TEST_ERROR + + /* Re-open the file with alignment and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl1)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* calculate fragment for alignment of block 30 */ + if ((tmp = file_size % alignment)) + mis_align = alignment - tmp; + + accum = mis_align + TEST_BLOCK_SIZE30; + + /* Allocate a block of 30 from file allocation */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (addr1 % alignment) TEST_ERROR + + /* there should be nothing in the aggregator */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if (ma_addr || ma_size) TEST_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + } + + /* calculate fragment for alignment of block 50 */ + mis_align = 0; + if ((tmp = (file_size + accum) % alignment)) + mis_align = alignment - tmp; + accum += (mis_align + TEST_BLOCK_SIZE50); + + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if (addr2 % alignment) TEST_ERROR + + /* there should be nothing in the aggregator */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if (ma_addr || ma_size) TEST_ERROR + + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + } + + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_try_shrink() of file allocation with alignment: test 2"); + + /* Re-open the file with alignment and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl1)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* allocate a block of 50 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + /* address should be aligned */ + if (addr1 % alignment) TEST_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl1)) < 0) + FAIL_STACK_ERROR + + /* shrink the block */ + status = H5MF_try_shrink(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE50); + if (status <= 0) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + if (new_file_size != (file_size-TEST_BLOCK_SIZE50)) TEST_ERROR + + PASSED() + + TESTING("H5MF_try_extend() of file allocation with alignment: test 3"); + + /* Re-open the file with alignment and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl1)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* allocate a block of 50 */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + /* address should be aligned */ + if (addr1 % alignment) TEST_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl1)) < 0) + FAIL_STACK_ERROR + + /* try to extend the block */ + extended = H5MF_try_extend(f, H5P_DATASET_XFER_DEFAULT, type, (haddr_t)addr1, (hsize_t)TEST_BLOCK_SIZE50, (hsize_t)TEST_BLOCK_SIZE30); + + if (extended <=0) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + if((new_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + if (new_file_size != (file_size+TEST_BLOCK_SIZE30)) TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_eoa() */ + +/* + * To verify that a block allocated from the free-space manager is aligned + * + * Alignment = 1024 or 4096 + * + * Test 1: + * Add section A with an aligned address to free-space manager (addr=alignment, size=50) + * Allocate a block of size=50 + * The returned space's address should be same as section A's address + * + * Test 2: + * Add section A to free-space manager (addr=70, size=8000): + * section A is mis-aligned but the size is big enough for allocation with alignment + * Allocate a block of size=600 + * The returned space should be allocated from section A with an aligned address: + * address=alignment size=600 + * There will be 2 sections in free-space: (alignment = 1024 or alignment = 4096) + * the fragment left from aligning section A: [70, 954] or [70, 4026] + * the section left after allocating block A: [1624, 416] or [4696, 3374] + * H5MF_try_extend() the block of size 600 by 200 should succeed: + * the existing fragment left from aligning section A: [70, 954] or [70, 4026] + * the section left after extending block A: [1824, 216] or [4896, 3174] + * + * Test 3: + * Add section A to free-space manager (addr=70, size=700): + * section A is mis-aligned but the size is not big enough for allocation with alignment + * Allocate a block of size=40 + * The free-space manager is unable to fulfill the request + * The block is allocated from file allocation and should be aligned + */ +static int +test_mf_align_fs(hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + h5_stat_size_t file_size; + H5F_t *f = NULL; /* Internal file object pointer */ + H5FD_mem_t type; + H5MF_free_section_t *sect_node = NULL; + haddr_t addr; + frspace_state_t state; + H5MF_sect_ud_t udata; + htri_t extended; + hsize_t alignment=0, tmp=0, mis_align=0; + + TESTING("H5MF_alloc() of free-space manager with alignment: test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + sect_node = H5MF_sect_simple_new((haddr_t)alignment, (hsize_t)TEST_BLOCK_SIZE50); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* Add section A to free-space manager */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_BLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Allocate a block of 50 */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + /* Verify that the allocated block is section A in free-space */ + if (addr != (haddr_t)alignment) TEST_ERROR + if (addr % alignment) TEST_ERROR + + state.tot_space -= TEST_BLOCK_SIZE50; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free the block to free-space */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)TEST_BLOCK_SIZE50); + + state.tot_space += TEST_BLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("H5MF_alloc() of free-space manager with alignment: test 2"); + + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + sect_node = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR70, (hsize_t)TEST_BLOCK_SIZE8000); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* Add section A to free-space manager */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_BLOCK_SIZE8000; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Allocate a block of 600 */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE600); + + /* Verify that the allocated block is aligned */ + if (addr % alignment) TEST_ERROR + + /* should have 1 more section in free-space */ + state.tot_space -= TEST_BLOCK_SIZE600; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* try to extend the block */ + extended = H5MF_try_extend(f, H5P_DATASET_XFER_DEFAULT, type, (haddr_t)addr, (hsize_t)TEST_BLOCK_SIZE600, (hsize_t)TEST_BLOCK_SIZE200); + + if (extended <=0) TEST_ERROR + + /* space should be decreased by 200, # of sections remain the same */ + state.tot_space -= TEST_BLOCK_SIZE200; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free the block to free-space manager */ + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr, (hsize_t)(TEST_BLOCK_SIZE600+TEST_BLOCK_SIZE200)); + + /* only 1 section in free-space because of merging */ + state.tot_space += (TEST_BLOCK_SIZE600+TEST_BLOCK_SIZE200); + state.tot_sect_count = 1; + state.serial_sect_count = 1; + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("H5MF_alloc() of free-space manager with alignment: test 3"); + + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + if(H5MF_alloc_start(f, H5P_DATASET_XFER_DEFAULT, type, TRUE) < 0) + TEST_ERROR + if (f->shared->fs_state[type] != H5F_FS_STATE_OPEN) + TEST_ERROR + if (f->shared->fs_man[type]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + sect_node = H5MF_sect_simple_new((haddr_t)TEST_BLOCK_ADDR70, (hsize_t)TEST_BLOCK_SIZE700); + + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = H5P_DATASET_XFER_DEFAULT; + udata.alloc_type = type; + udata.allow_sect_absorb = TRUE; + + /* Add section A to free-space manager */ + if (H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, f->shared->fs_man[type], (H5FS_section_info_t *)sect_node, H5FS_ADD_RETURNED_SPACE, &udata)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_BLOCK_SIZE700; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + /* + * Allocate a block of 40 + * Since free-space manager cannot fulfull the request because of alignment, + * the block is obtained from file allocation + */ + addr = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)(TEST_BLOCK_SIZE40)); + + /* Verify that the allocated block is aligned */ + if (addr % alignment) + TEST_ERROR + + /* verify that the allocated block is from file allocation, not section A in free-space */ + if (!(addr >= (haddr_t)file_size)) TEST_ERROR + + /* calculate fragment for alignment of block 40 from file allocation */ + if ((tmp = file_size % alignment)) + mis_align = alignment - tmp; + + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + /* free-space info should be the same */ + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_fs() */ + +/* + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 1024 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size > aggr->size and < aggr->alloc_size + * Result: + * An "aggr->alloc_size" block is allocated from file allocation for the aggregator + * EOA is 3072 + * The first block of 30 is allocated from the aggregator and should be aligned + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * There is space of 2018 left in meta_aggr + * + * Allocate second block (50) from meta_aggr: + * (request-size + fragment size) <= aggr->size + * Result: + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[1054, 994] + * There is space of 974 left in meta_aggr + * + * Allocate third block (80) from meta_aggr: + * (request-size + fragment size) > aggr->size + * request-size < meta_aggr->alloc_size + * fragment size < (meta_aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of "meta_aggr->alloc_size" is extended from file allocation for meta_aggr + * EOA is 5120 + * The third block of 80 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[2098, 974] + * There is space of 1968 left in meta_aggr + * + * Allocate fourth block (1970) from meta_aggr: + * (request-size + fragment size) is <= aggr->size + * fragment size > (aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of aggr->alloc_size + fragment size - (aggr->alloc_size - request-size)) + * is extended from file allocation for meta_aggr + * The third block of 1970 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[3152, 944] + * There is space of 1968 left in meta_aggr + * EOA is at 8034 + * + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (aggregator is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A meta_aggr->alloc_size block is allocated from file allocation for the aggregator + * The first block of 30 is allocated from the aggregator and should be aligned + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * There is space of 2018 left in meta_aggr + * EOA is at 6144 + * + * Allocate second block (50) from meta_aggr: + * (request-size + fragment size) is > meta_aggr->size + * request-size < meta_aggr->alloc_size + * fragment size > (meta_aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of meta_aggr->alloc_size + (fragment size - (meta_aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[4126, 4066] + * There is space of 2018 left in meta_aggr + * EOA is at 10260 + * + * Allocate third block (80) from meta_aggr: + * (request-size + fragment size) is > meta_aggr->size + * request-size < meta_aggr->alloc_size + * fragment size > (meta_aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of meta_aggr->alloc_size + (fragment size - (meta_aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * The third block of 80 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[8242, 4046] + * There is space of 2018 left in meta_aggr + * EOA is at 14386 + * + * Allocate fourth block (1970) from meta_aggr: + * (request-size + fragment size) > meta_aggr->size + * request-size < meta_aggr->alloc_size + * fragment size > (meta_aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of meta_aggr->alloc_size + (fragment size - (meta_aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * The fourth block of 1970 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[12368, 4016] + * There is space of 2018 left in meta_aggr + * EOA is at 20372 + */ +static int +test_mf_align_alloc1(hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; /* File size */ + + H5FD_mem_t type; + haddr_t addr1, addr2, addr3, addr4; + frspace_state_t state; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, mis_align=0; + hsize_t alignment=0, tmp=0; + + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* calculate fragment for alignment of block 30 */ + if ((tmp = file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (addr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 is freed to free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr1 + TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 50 */ + mis_align = 0; + if ((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 50 from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if (addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 50 is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr2 + TEST_BLOCK_SIZE50) != ma_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 80 */ + mis_align = 0; + if ((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + addr3 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE80); + + /* Verify that the allocated block is aligned */ + if (addr3 % alignment) TEST_ERROR + + /* fragment for alignment of block 80 is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr3 + TEST_BLOCK_SIZE80) != ma_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 1970 */ + mis_align = 0; + if ((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 1970 from meta_aggr */ + addr4 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE1970); + + /* Verify that the allocated block is aligned */ + if (addr4 % alignment) TEST_ERROR + + /* fragment for alignment of block 1970 is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr4 + TEST_BLOCK_SIZE1970) != ma_addr) + TEST_ERROR + + /* Verify total size of free space after all the allocations */ + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr3, (hsize_t)TEST_BLOCK_SIZE80); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr3, (hsize_t)TEST_BLOCK_SIZE1970); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc1() */ + +/* + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 1024 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A meta_aggr->alloc_size block is allocated from file allocation for the aggregator + * The first block of 30 is allocated from the aggregator and should be aligned + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * There is space of 2018 left in meta_aggr + * EOA is 3072 + * + * Allocate second block (50) from meta_aggr: + * (request-size+fragment size) <= aggr->size + * Result: + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[1054, 994] + * There is space of 974 left in meta_aggr + * + * Allocate first block (30) from sdata_aggr: (sdata_aggr is empty) + * request-size is > sdata_aggr->size and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from sdata_aggr and should be aligned + * EOA is 5120 + * + * Allocate third block (80) from meta_aggr: + * request-size+fragment size is > meta_aggr->size + * sdata_aggr is at EOA but has not used up more than sdata_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * The unused space in meta_aggr is freed to free-space [2098, 974] + * meta_aggr is updated to point to the new block + * The third block of 80 is allocated from meta_aggr and should be aligned + * EOA is 7168 + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > aggr->size and < aggr->alloc_size + * Result: + * A meta_aggr->alloc_size block is allocated from file allocation for the aggregator + * The first block of 30 is allocated from the aggregator and should be aligned + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * There is space of 2018 left meta_aggr + * EOA is at 6144 + * + * Allocate second block (50) from meta_aggr: + * (request-size + fragment size) > aggr->size + * request-size < aggr->alloc_size + * fragment size > (aggr->alloc_size - request-size) + * Result: + * A block of aggr->alloc_size + (fragment size - (aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[4126, 4066] + * There is space of 2018 left in meta_aggr + * EOA is at 10260 + * + * Allocate first block (30) from sdata_aggr: (sdata_aggr is empty) + * request-size is > sdata_aggr->size and < sdata_aggr->alloc_size + * meta_aggr is at EOA and has used up more than meta_aggr->alloc_size + * Result: + * The remaining space in meta_aggr is freed to free-space [8242, 2018] and shrunk since at EOF + * meta_aggr is reset to 0 + * A block of sdata_aggr->alloc_size is obtained via file allocation + * Fragment from alignment of file allocation is freed to free-space: [8242, 4046] + * The first block of 30 is allocated from sdata_aggr and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 14336 + * + * Allocate third block (80) from meta_aggr: + * (request-size + fragment size) is > meta_aggr->size + * request-size < meta_aggr->alloc_size + * sdata_aggr is at EOA but has not used up more than sdata_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation for the aggregator + * Fragment from alignment of file allocation is freed to free-space:[14336, 2048] + * Since this fragment adjoins sdata_aggr and fulfills "absorb" condition, + * the space left in sdata_aggr is absorbed into the fragment and freed to free-space: [12318, 2018] + * other_aggr is reset to 0 + * The third block of 80 is allocated from the aggregator and should be aligned + * There is space of 1968 left in meta_aggr + * EOA is at 18432 + */ +static int +test_mf_align_alloc2(hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; /* File size */ + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3, saddr1; + frspace_state_t state; + haddr_t ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, sdata_size=0, mis_align=0; + hsize_t alignment=0, tmp=0; + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 2"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* calculate fragment for alignment of block 30 */ + if ((tmp = file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (addr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 is freed to free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr1 + TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* fragment for alignment of block 50 is freed to free-space */ + mis_align = 0; + if ((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if (addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 50 is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr2 + TEST_BLOCK_SIZE50) != ma_addr) + TEST_ERROR + + /* + * Calculate fragment for alignment of block 30 in sdata_aggr: + * + * For alignment = 1024, alloc_size = 2048: + * block 30 is allocated from (ma_addr + ma_size), + * which is already aligned + * + * For alignment = 4096, alloc_size = 2048: + * since remaining space in meta_aggr is freed and shrunk, + * block 30 is allocated from ma_addr + */ + mis_align = 0; + if ((alignment == TEST_ALIGN1024) && (tmp = ((ma_addr + ma_size) % alignment))) + mis_align = alignment - tmp; + else if ((alignment == TEST_ALIGN4096) && (tmp = (ma_addr % alignment))) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* fragment for alignment of block 30 for sdata_aggr is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + /* Verify that the allocated block is aligned */ + if (saddr1 % alignment) TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if (sdata_addr != (saddr1 + TEST_BLOCK_SIZE30)) TEST_ERROR + + /* + * Calculate fragment for the allocation of block 80 from meta_aggr: + * + * For alignment = 1024, alloc_size = 2048: + * fragment for unused space in meta_aggr is freed to free-space + * For alignment = 4096, alloc_size = 2048: + * fragment from alignment of file allocation absorbs sdata_aggr's remaining space + */ + mis_align = 0; + if ((alignment == TEST_ALIGN1024) && (tmp = (ma_addr % alignment))) + mis_align = alignment - tmp; + else if ((alignment == TEST_ALIGN4096) && (tmp = (sdata_addr % alignment))) + mis_align = alignment - tmp; + + /* Allocate a block of 80 from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE80); + + /* Verify that the allocated block is aligned */ + if (addr3 % alignment) TEST_ERROR + + /* fragment for alignment of block 80 is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr3 + TEST_BLOCK_SIZE80) != ma_addr) + TEST_ERROR + + /* Verify total size of free space after all the allocations */ + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr1, (hsize_t)TEST_BLOCK_SIZE30); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr2, (hsize_t)TEST_BLOCK_SIZE50); + H5MF_xfree(f, type, H5P_DATASET_XFER_DEFAULT, addr3, (hsize_t)TEST_BLOCK_SIZE80); + H5MF_xfree(f, stype, H5P_DATASET_XFER_DEFAULT, saddr1, (hsize_t)TEST_BLOCK_SIZE30); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc2() */ + +/* + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 1024 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation for the aggregator + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 3072 + * + * Allocate second block (50) from meta_aggr: + * (request-size+fragment size) is <= aggr->size + * Result: + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[1054, 994] + * There is space of 974 left in the aggregator + * + * Allocate first block (30) from other_aggr: (nothing in other_aggr) + * request-size is > what is left in other_aggr->size and < other_aggr->alloc_size + * Result: + * A "other_aggr->alloc_size" block is allocated from file allocation for other_aggr + * The first block of 30 is allocated from other_aggr and should be aligned + * There is space of 2018 left in other_aggr->size + * EOA is 5120 + * + * Allocate second block (50) from sdata_aggr: + * (request-size+fragment size) < sdata_aggr->size + * Result: + * The second block of 50 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[3102, 994] + * There is space of 974 left in sdata_aggr + * + * Allocate third block (80) from sdata_aggr: + * (request-size+fragment size) is >= sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * sdata_aggr is at EOA + * Result: + * Another block of sdata_aggr->alloc_size is extended from file allocation for sdata_aggr + * The third block of 80 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[4146, 974] + * There is space of 1968 left in sdata_aggr + * EOA is 7168 + * + * Allocate third block (1034) from meta_aggregator: + * (request-size + alignment) > meta_aggr->size but < meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * The unused space in sdata_aggr is freed to free-space [5200, 1968] then shrunk + * sdata_aggr is reset to 0 + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space [5200, 944] + * The unused space in meta_aggr is freed to free-space [2098, 974] + * The meta_aggr is updated to point to the new space + * The block of 1034 is allocated from the new block and should be aligned + * There is space of 1014 left in meta_aggr + * EOA is 8192 + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > what is left in aggr->size and < aggr->alloc_size + * Result: + * A meta_aggr->alloc block is allocated from file allocation for the aggregator + * The first block of 30 is allocated from the aggregator and should be aligned + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * There is space of 2018 left in meta_aggr + * EOA is at 6144 + * + * Allocate second block (50) from meta_aggr: + * (request-size + fragment size) is > what is left in aggr->size + * request-size < aggr->alloc_size + * fragment size > (aggr->alloc_size - request-size) + * Result: + * A block of aggr->alloc_size + (fragment size - (aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[4126, 4066] + * There is space of 2018 left in meta_aggr + * EOA is at 10260 + * + * Allocate first block (30) from sdata_aggr: (sdata_aggr is empty) + * request-size > sdata_aggr->size and < sdata_aggr->alloc_size + * meta_aggr is at EOA and has used up more than meta_aggr->alloc_size + * Result: + * The remaining space in meta_aggr is freed to free-space [8242, 2018] and shrunk + * since at EOF + * meta_aggr is reset to 0 + * A block of sdata_aggr->alloc_size is obtained via file allocation + * Fragment from alignment of file allocation is freed to free-space: [8242, 4046] + * The first block of 30 is allocated from sdata_aggr and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 14336 + * + * Allocate second block (50) from sdata_aggr: + * request-size is > sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * fragment size > (sdata_aggr->alloc_size - request-size) + * Result: + * A block of sdata_aggr->alloc_size + (fragment size - (sdata_aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[12318, 4066] + * The second block of 50 is allocated from the aggregator and should be aligned + * There is space of 2018 left in the sdata_aggr + * EOA is at 18452 + * + * Allocate third block (80) from sdata_aggr: + * request-size + fragment size is > sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * fragment size > (sdata_aggr->alloc_size - request-size) + * Result: + * A block of sdata_aggr->alloc_size + (fragment size - (sdata_aggr->alloc_size - request-size) + * is allocated from file allocation for the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[16434, 4046] + * The third block of 80 is allocated from the aggregator and should be aligned + * There is space of 2018 left in the sdata_aggr + * EOA is at 22578 + * + * Allocate third block (1034) from meta_aggregator: + * (request-size + fragment size) is > meta_aggr->size but request-size < meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * The remaining space in sdata_aggr is freed to free-space [20560, 2018] then shrunk + * sdata_aggr is reset to 0 + * There is nothing in meta_aggr + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space [20560, 4016] + * EOA is 26624 + * The meta_aggr is updated to point to the new space + * The block of 1034 is allocated from the new block and should be aligned + * There is space of 1014 left in meta_aggr + */ +static int +test_mf_align_alloc3(hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3; + haddr_t saddr1, saddr2, saddr3; + frspace_state_t state; + haddr_t ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, sdata_size=0, mis_align=0; + hsize_t alignment=0, tmp=0; + + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 3"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* calculate fragment for alignment of block 30 */ + if ((tmp = file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (addr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 is freed to free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1 + TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 50 */ + mis_align = 0; + if ((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 50 from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if (addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 50 is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr2 + TEST_BLOCK_SIZE50) != ma_addr) + TEST_ERROR + + /* + * Calculate fragment for alignment of block 30 in sdata_aggr: + * + * For alignment = 1024, alloc_size = 2048: + * block 30 is allocated from (ma_addr + ma_size), + * which is already aligned + * + * For alignment = 4096, alloc_size = 2048: + * since remaining space in meta_aggr is freed and shrunk, + * block 30 is allocated from ma_addr + */ + mis_align = 0; + if ((alignment == TEST_ALIGN1024) && (tmp = ((ma_addr + ma_size) % alignment))) + mis_align = alignment - tmp; + else if ((alignment == TEST_ALIGN4096) && (tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (saddr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 for sdata_aggr is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if (sdata_addr != (saddr1+TEST_BLOCK_SIZE30)) TEST_ERROR + + /* calculate fragment for alignment of block 50 in sdata_aggr */ + mis_align = 0; + if ((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 50 from sdata_aggr */ + saddr2 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if (saddr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 50 for sdata_aggr is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if (sdata_addr != (saddr2 + TEST_BLOCK_SIZE50)) TEST_ERROR + + /* calculate fragment for alignment of block 80 in sdata_aggr */ + mis_align = 0; + if ((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 80 from sdata_aggr */ + saddr3 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE80); + + /* Verify that the allocated block is aligned */ + if (saddr3 % alignment) TEST_ERROR + + /* fragment for alignment of block 80 for sdata_aggr is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr3 + TEST_BLOCK_SIZE80) != sdata_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 1034 */ + mis_align = 0; + if ((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 1034 for meta_aggr */ + addr3 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE1034); + + /* Verify that the allocated block is aligned */ + if (addr3 % alignment) TEST_ERROR + + /* fragment for alignment of block 1034 for meta_aggr is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + /* calculate unused space in meta_aggr that is freed to free-space after block 1034 */ + mis_align = 0; + if ((alignment == TEST_ALIGN1024) && (tmp = (ma_addr % alignment))) + mis_align = alignment - tmp; + + /* fragment for unused space in meta_aggr after block 1034 is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr3 + TEST_BLOCK_SIZE1034) != ma_addr) + TEST_ERROR + + /* Verify total size of free space after all allocations */ + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc3() */ + + +/* + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * The first block of 30 is allocated from meta_aggr and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 3072 + * + * Allocate second block (2058) from meta_aggr: + * (request-size+fragment) is > meta_aggr->size and request-size is > meta_aggr->alloc_size + * meta_aggr is at EOA + * Result: + * The second block of 2058 + fragment is extended and merged together with meta_aggr + * The block of 2058 is allocated out of the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[1054, 994] + * There is space of 2018 (same as before) left in meta_aggr + * EOA is 6124 + * + * Allocate third block (5) from meta_aggr: + * request-size+fragment < meta_aggr->size + * Result: + * A block of 5 is allocated from the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[4106, 1014] + * There is space of 999 left in meta_aggr + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * The first block of 30 is allocated from meta_aggr and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 6144 + * + * Allocate second block (2058) from meta_aggr: + * (request-size+fragment) is > meta_aggr->size and request-size is > meta_aggr->alloc_size + * meta_aggr is at EOA + * Result: + * The second block of 2058 + fragment is extended and merged together with meta_aggr + * The block of 2058 is allocated out of the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[4126, 4066] + * There is space of 2018 (same as before) left in meta_aggr + * EOA is 12268 + * + * Allocate third block (5) from meta_aggr: + * request-size+fragment is > meta_aggr->size + * request-size < meta_aggr->alloc_size + * fragment < (meta_aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of meta_aggr->alloc_size is extended from file allocation for the aggregator + * A block of 5 is allocated from the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[10250, 2038] + * There is space of 2023 left in meta_aggr + * + */ +static int +test_mf_align_alloc4(hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; + H5FD_mem_t type; + haddr_t addr1, addr2, addr3; + frspace_state_t state; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, saved_ma_size=0; + hsize_t alignment=0, mis_align=0, tmp=0; + + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 4"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* calculate fragment for alignment of block 30 */ + if ((tmp = file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (addr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 is freed to free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + saved_ma_size = ma_size; + if ((addr1+TEST_BLOCK_SIZE30) != ma_addr) TEST_ERROR + + /* calculate fragment for alignment of block 2058 */ + mis_align = 0; + if ((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 2058 from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE2058); + + /* Verify that the allocated block is aligned */ + if (addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 2058 is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr2 + TEST_BLOCK_SIZE2058) != ma_addr) TEST_ERROR + + /* meta_aggr->size remains the same */ + if (ma_size != saved_ma_size) TEST_ERROR + + /* calculate fragment for alignment of block 5 from meta_aggr */ + mis_align = 0; + if ((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 5 from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE5); + + /* fragment for alignment of block 5 is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + /* Verify that the allocated block is aligned */ + if (addr3 % alignment) TEST_ERROR + + /* Verify total size of free space after all allocations */ + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc4() */ + +/* + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 1024 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * The first block of 30 is allocated from meta_aggr and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 3072 + * + * Allocate first block (30) from sdata_aggr: (nothing in the aggregator) + * A block of sdata_aggr->alloc_size is allocated from file allocation + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 5120 + * + * Allocate second block (2058) from meta_aggr: + * (request-size + fragment size) > meta_aggr->size and > meta_aggr->alloc_size + * sdata_aggr is at EOA but has not used up sdata_aggr->alloc_size + * Result: + * A block of 2058 is allocated from file allocation + * EOA is 7178 + * Nothing is changed in meta_aggr and sdata_aggr + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * The first block of 30 is allocated from meta_aggr and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 6144 + * + * Allocate first block (30) from sdata_aggr: (meta_aggr is empty) + * meta_aggr is at EOA but has not used up more than meta_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[6144, 2048] + * This fragment adjoins meta_aggr and fulfills "absorb" condition, + * the remaining space left in meta_aggr is absorbed into the fragment and + * freed to free-space: [4126, 2018] + * meta_aggr is reset to 0 + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 10240 + * + * Allocate second block (2058) from meta_aggr: + * request-size + fragment size is > meta_aggr->size + * request_size is > meta_aggr->alloc_size + * sdata_aggr is at EOA but has not used up more than sdata_aggr->alloc_size + * Result: + * A block of 2058 is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[10240, 2048] + * This fragment adjoins sdata_aggr and fulfills "absorb" condition, + * the remaining space left in sdata_aggr is absorbed into the fragment and + * freed to free-space: [8222, 2018] + * sdata_aggr is reset to 0 + * EOA is 14346 + * meta_aggr and sdata_aggr are all 0 + */ +static int +test_mf_align_alloc5(hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; + H5FD_mem_t type, stype; + haddr_t addr1, addr2, saddr1; + frspace_state_t state; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + haddr_t sdata_addr=HADDR_UNDEF, new_sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0, sdata_size=0, new_sdata_size=0; + hsize_t alignment=0, mis_align=0, tmp=0; + + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 5"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* calculate fragment for alignment of block 30 */ + if ((tmp = file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (addr1 % alignment) TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr1 + TEST_BLOCK_SIZE30) != ma_addr) TEST_ERROR + + /* fragment for alignment of block 30 is freed to free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + /* calculate fragment for alignment of block 30 from sdata_aggr */ + mis_align = 0; + if ((alignment == TEST_ALIGN1024) && (tmp = (ma_addr + ma_size) % alignment)) + mis_align = alignment - tmp; + else if ((alignment == TEST_ALIGN4096) && (tmp = (ma_addr % alignment))) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (saddr1 % alignment) TEST_ERROR + + /* fragment of alignment for block 30 in sdata_aggr is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr1+TEST_BLOCK_SIZE30) != sdata_addr) TEST_ERROR + + /* calculate fragment for alignment of block 2058 from meta_aggr */ + mis_align = 0; + if ((alignment == TEST_ALIGN1024) && (tmp = (sdata_addr + sdata_size) % alignment)) + mis_align = alignment - tmp; + else if ((alignment == TEST_ALIGN4096) && (tmp = (sdata_addr % alignment))) + mis_align = alignment - tmp; + + /* Allocate a block of 2058 from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE2058); + + /* Verify that the allocated block is aligned */ + if (addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 2058 is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + /* Verify total size of free space after all allocations */ + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + /* nothing is changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (alignment == TEST_ALIGN1024 && (new_ma_addr != ma_addr || new_ma_size != ma_size)) + TEST_ERROR + else if (alignment == TEST_ALIGN4096 && (new_ma_addr != 0 || new_ma_size != 0)) + TEST_ERROR + + /* nothing is changed in sdata_aggr */ + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &new_sdata_addr, &new_sdata_size); + if (alignment == TEST_ALIGN1024 && (new_sdata_addr != sdata_addr || new_sdata_size != sdata_size)) + TEST_ERROR + else if (alignment == TEST_ALIGN4096 && ((new_sdata_addr != 0 || new_sdata_size != 0))) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc5() */ + + +/* + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 1024 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in meta_aggr->size + * EOA is 3072 + * + * Allocate first block (30) from sdata_aggr: (sdata_aggr is empty) + * request_size > sdata_aggr->size and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is allocated from file allocation + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 5120 + * + * Allocate second block (50) from sdata_aggr: + * (request-size+fragment size) <= sdata_aggr->size + * Result: + * The second block of 50 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[3102, 994] + * There is space of 974 left in sdata_aggr + * + * Allocate third block (80) from sdata_aggr: + * (request-size+fragment size) > sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * fragment size < (sdata_aggr->alloc_size - request-size) + * Result: + * Another block of sdata_aggr->alloc_size block is extended from file allocation + * for sdata_aggr + * The third block of 80 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[4146, 974] + * There is space of 1968 left in sdata_aggr + * EOA is 7168 + * + * Allocate second block (2058) from meta_aggr: + * request-size + fragment size is > meta_aggr->size + * request-size is > meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * The remaining space in sdata_aggr is freed to free-space and shrunk + * sdata_aggr is reset to 0 + * A block of 2058 is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[5200, 944] + * EOA is at 8202 + * meta_aggr is unchanged + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is emtpy) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 6144 + * + * Allocate first block (30) from sdata_aggr: (sdata_aggr is empty) + * request_size > sdata_aggr->size and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space: [6144, 2048] + * This fragment adjoins meta_aggr and fulfills "absorb" condition, + * the remaining space left in meta_aggr is absorbed into the fragment and + * freed to free-space:[4126, 2018] + * meta_aggr is reset to 0 + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 5120 + * + * Allocate second block (50) from sdata_aggr: + * (request-size+fragment size) is <= sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * fragment size > (sdata_aggr->alloc_size - request-size) + * Result: + * A block of sdata_aggr->alloc_size + (fragment size - (sdata_aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * The second block of 50 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[8222, 4066] + * There is space of 2018 left in sdata_aggr + * EOA is at 14356 + * + * Allocate third block (80) from sdata_aggr: + * (request-size+fragment size) is > sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * fragment size > (sdata_aggr->alloc_size - request-size) + * Result: + * A block of sdata_aggr->alloc_size+(fragment size-(sdata_aggr->alloc_size-request-size)) + * is extended from file allocation for sdata_aggr + * The third block of 80 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[12338, 4046] + * There is space of 2018 left in sdata_aggr + * EOA is 18482 + * + * Allocate second block (2058) from meta_aggr: + * request-size + fragment size is > meta_aggr->size + * request-size is > meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * The remaining space in sdata_aggr is freed to free-space and shrunk: [16464, 2018] + * sdata_aggr is reset to 0 + * A block of 2058 is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[16464, 4016] + * EOA is at 22538 + * meta_aggr is unchanged + */ +static int +test_mf_align_alloc6(hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; + H5FD_mem_t type, stype; + haddr_t addr1, addr2; + haddr_t saddr1, saddr2, saddr3; + frspace_state_t state; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0, sdata_size=0; + hsize_t alignment=0, mis_align=0, tmp=0; + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 6"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* calculate fragment for alignment of block 30 */ + if ((tmp = file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (addr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 in meta_aggr is freed to free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1+TEST_BLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 30 in sdata_aggr */ + mis_align = 0; + if ((alignment == TEST_ALIGN1024) && (tmp = (ma_addr + ma_size) % alignment)) + mis_align = alignment - tmp; + else if ((alignment == TEST_ALIGN4096) && (tmp = (ma_addr % alignment))) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (saddr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 in sdata_aggr is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if (sdata_addr != (saddr1+TEST_BLOCK_SIZE30)) TEST_ERROR + + /* calculate fragment for alignment of block 50 in sdata_aggr */ + mis_align = 0; + if ((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 50 from sdata_aggr */ + saddr2 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if (saddr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 50 in sdata_aggr is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if (sdata_addr != (saddr2+TEST_BLOCK_SIZE50)) TEST_ERROR + + /* calculate fragment for alignment of block 80 in sdata_aggr */ + mis_align = 0; + if ((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 80 from sdata_aggr */ + saddr3 = H5MF_alloc(f, stype, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE80); + + /* Verify that the allocated block is aligned */ + if (saddr3 % alignment) TEST_ERROR + + /* fragment for alignment of block 80 in sdata_aggr is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if (sdata_addr != (saddr3+TEST_BLOCK_SIZE80)) TEST_ERROR + + /* calculate fragment for alignment of block 2058 */ + /* remaining space in sdata_aggr is freed and shrunk */ + mis_align = 0; + if ((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 2058 from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5P_DATASET_XFER_DEFAULT, (hsize_t)TEST_BLOCK_SIZE2058); + + /* Verify that the allocated block is aligned */ + if (addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 2058 is freed to free-space */ + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + + if (alignment == TEST_ALIGN1024 && (new_ma_addr != ma_addr || new_ma_size != ma_size)) + TEST_ERROR + else if (alignment == TEST_ALIGN4096 && (new_ma_addr != 0 || new_ma_size != 0)) + TEST_ERROR + + if (sdata_addr != 0 || sdata_size != 0) + TEST_ERROR + + if(check_stats(f->shared->fs_man[type], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc6() */ + + +int +main(void) +{ + hid_t fapl = -1; /* File access property list for data files */ + hid_t new_fapl = -1; /* File access property list for alignment & aggr setting */ + unsigned nerrors = 0; /* Cumulative error count */ + test_type_t curr_test; + + fapl = h5_fileaccess(); + if((new_fapl = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* alignment is not set for the following tests */ + if(H5Pset_alignment(fapl, (hsize_t)1, (hsize_t)1) < 0) + TEST_ERROR + + /* meta/small data is set to 2048 for the following tests */ + if(H5Pset_meta_block_size(fapl, (hsize_t)TEST_BLOCK_SIZE2048) < 0) + TEST_ERROR + if(H5Pset_small_data_block_size(fapl, (hsize_t)TEST_BLOCK_SIZE2048) < 0) + TEST_ERROR + + nerrors += test_mf_eoa(fapl); + nerrors += test_mf_eoa_shrink(fapl); + nerrors += test_mf_eoa_extend(fapl); + + /* interaction with free-space manager */ + nerrors += test_mf_fs_start(fapl); + nerrors += test_mf_fs_alloc_free(fapl); + nerrors += test_mf_fs_extend(fapl); + nerrors += test_mf_fs_absorb(fapl); + + /* interaction with meta/sdata aggregator */ + nerrors += test_mf_aggr_alloc1(fapl); + nerrors += test_mf_aggr_alloc2(fapl); + nerrors += test_mf_aggr_alloc3(fapl); + nerrors += test_mf_aggr_alloc4(fapl); + nerrors += test_mf_aggr_alloc5(fapl); + nerrors += test_mf_aggr_alloc6(fapl); + nerrors += test_mf_aggr_alloc7(fapl); + nerrors += test_mf_aggr_extend(fapl); + nerrors += test_mf_aggr_absorb(fapl); + + /* interaction with file allocation */ + nerrors += test_mf_eoa(fapl); + nerrors += test_mf_eoa_shrink(fapl); + nerrors += test_mf_eoa_extend(fapl); + + /* interaction with free-space manager */ + nerrors += test_mf_fs_start(fapl); + nerrors += test_mf_fs_alloc_free(fapl); + nerrors += test_mf_fs_extend(fapl); + nerrors += test_mf_fs_absorb(fapl); + + /* interaction with meta/sdata aggregator */ + nerrors += test_mf_aggr_alloc1(fapl); + nerrors += test_mf_aggr_alloc2(fapl); + nerrors += test_mf_aggr_alloc3(fapl); + nerrors += test_mf_aggr_alloc4(fapl); + nerrors += test_mf_aggr_alloc5(fapl); + nerrors += test_mf_aggr_alloc6(fapl); + nerrors += test_mf_aggr_alloc7(fapl); + nerrors += test_mf_aggr_extend(fapl); + nerrors += test_mf_aggr_absorb(fapl); + + /* + * tests for alignment + */ + + /* set meta/sdata block size = 2048 */ + if(H5Pset_meta_block_size(new_fapl, (hsize_t)TEST_BLOCK_SIZE2048) < 0) + TEST_ERROR + if(H5Pset_small_data_block_size(new_fapl, (hsize_t)TEST_BLOCK_SIZE2048) < 0) + TEST_ERROR + + for(curr_test = TEST_NORMAL; curr_test < TEST_NTESTS; curr_test++) { + + switch(curr_test) { + + case TEST_NORMAL: /* set alignment = 1024 */ + if(H5Pset_alignment(new_fapl, (hsize_t)0, (hsize_t)TEST_ALIGN1024) < 0) + TEST_ERROR + break; + + case TEST_AGGR_SMALL: /* set alignment = 4096 */ + if(H5Pset_alignment(new_fapl, (hsize_t)0, (hsize_t)TEST_ALIGN4096) < 0) + TEST_ERROR + break; + + default: + TEST_ERROR; + } /* end switch */ + + nerrors += test_mf_align_eoa(fapl, new_fapl); + nerrors += test_mf_align_fs(fapl, new_fapl); + nerrors += test_mf_align_alloc1(fapl, new_fapl); + nerrors += test_mf_align_alloc2(fapl, new_fapl); + nerrors += test_mf_align_alloc3(fapl, new_fapl); + nerrors += test_mf_align_alloc4(fapl, new_fapl); + nerrors += test_mf_align_alloc5(fapl, new_fapl); + nerrors += test_mf_align_alloc6(fapl, new_fapl); + } + + if(nerrors) + goto error; + puts("All free-space manager tests for file memory passed."); + + h5_cleanup(FILENAME, fapl); + + return (0); + +error: + puts("*** TESTS FAILED ***"); + H5E_BEGIN_TRY { + H5Pclose(fapl); + } H5E_END_TRY; + return (1); +} /* main() */ diff --git a/test/objcopy.c b/test/objcopy.c index 653da96..86a0d30 100755 --- a/test/objcopy.c +++ b/test/objcopy.c @@ -325,7 +325,7 @@ attach_reg_ref_attr(hid_t file_id, hid_t loc_id) /* create reg_ref of point selection */ if(H5Sselect_none(space_id) < 0) TEST_ERROR - if(H5Sselect_elements(space_id, H5S_SELECT_SET, num_points, coord) < 0) TEST_ERROR + if(H5Sselect_elements(space_id, H5S_SELECT_SET, num_points, (const hsize_t *)coord) < 0) TEST_ERROR if(H5Rcreate(&ref[1], file_id, dsetnamev, H5R_DATASET_REGION, space_id) < 0) TEST_ERROR /* create reg_ref attribute */ @@ -408,7 +408,7 @@ create_reg_ref_dataset(hid_t file_id, hid_t loc_id) if(H5Sselect_hyperslab(space_id,H5S_SELECT_SET,start,NULL,count,NULL) < 0) TEST_ERROR if(H5Rcreate(&ref[0], file_id, dsetnamev, H5R_DATASET_REGION, space_id) < 0) TEST_ERROR if(H5Sselect_none(space_id) < 0) TEST_ERROR - if(H5Sselect_elements(space_id, H5S_SELECT_SET, num_points, coord) < 0) TEST_ERROR + if(H5Sselect_elements(space_id, H5S_SELECT_SET, num_points, (const hsize_t *)coord) < 0) TEST_ERROR if(H5Rcreate(&ref[1], file_id, dsetnamev, H5R_DATASET_REGION, space_id) < 0) TEST_ERROR if(H5Dwrite(dsetr_id, H5T_STD_REF_DSETREG, H5S_ALL, H5S_ALL, H5P_DEFAULT,ref) < 0) TEST_ERROR if(H5Dclose(dsetr_id) < 0) TEST_ERROR diff --git a/test/tfile.c b/test/tfile.c index ff8aa2b..b5f024c 100644 --- a/test/tfile.c +++ b/test/tfile.c @@ -1191,6 +1191,8 @@ static void test_file_freespace(void) { hid_t file; /* File opened with read-write permission */ + h5_stat_size_t empty_filesize; /* Size of file when empty */ + h5_stat_size_t mod_filesize; /* Size of file after being modified */ hssize_t free_space; /* Amount of free space in file */ hid_t dspace; /* Dataspace ID */ hid_t dset; /* Dataset ID */ @@ -1202,10 +1204,20 @@ test_file_freespace(void) /* Output message about test being performed */ MESSAGE(5, ("Testing Low-Level File Free Space\n")); - /* Create the file (with read-write permission) */ + /* Create an "empty" file */ file = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); CHECK(file, FAIL, "H5Fcreate"); + ret = H5Fclose(file); + CHECK_I(ret, "H5Fclose"); + + /* Get the "empty" file size */ + empty_filesize = h5_get_file_size(FILE1); + + /* Re-open the file (with read-write permission) */ + file = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT); + CHECK_I(file, "H5Fopen"); + /* Check that the free space is 0 */ free_space = H5Fget_freespace(file); CHECK(free_space, FAIL, "H5Fget_freespace"); @@ -1244,7 +1256,7 @@ test_file_freespace(void) /* Check that there is the right amount of free space in the file */ free_space = H5Fget_freespace(file); CHECK(free_space, FAIL, "H5Fget_freespace"); - VERIFY(free_space, 2376, "H5Fget_freespace"); + VERIFY(free_space, 2008, "H5Fget_freespace"); /* Delete datasets in file */ for(u = 0; u < 10; u++) { @@ -1261,6 +1273,12 @@ test_file_freespace(void) /* Close file */ ret = H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); + + /* Get the file size after modifications*/ + mod_filesize = h5_get_file_size(FILE1); + + /* Check that the file reverted to empty size */ + VERIFY(mod_filesize, empty_filesize, "H5Fget_freespace"); } /* end test_file_freespace() */ /**************************************************************** diff --git a/test/trefer.c b/test/trefer.c index f8e2287..bf9692f 100644 --- a/test/trefer.c +++ b/test/trefer.c @@ -407,7 +407,7 @@ test_reference_region(void) coord1[7][0] = 9; coord1[7][1] = 0; coord1[8][0] = 7; coord1[8][1] = 1; coord1[9][0] = 3; coord1[9][1] = 3; - ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord1); + ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord1); CHECK(ret, FAIL, "H5Sselect_elements"); ret = (int)H5Sget_select_npoints(sid2); @@ -679,7 +679,7 @@ test_reference_region_1D(void) coord1[7][0] = 89; coord1[8][0] = 97; coord1[9][0] = 03; - ret = H5Sselect_elements(sid3, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord1); + ret = H5Sselect_elements(sid3, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord1); CHECK(ret, FAIL, "H5Sselect_elements"); ret = (int)H5Sget_select_npoints(sid3); @@ -1264,7 +1264,7 @@ test_reference_compat(void) coord1[7][0] = 9; coord1[7][1] = 0; coord1[8][0] = 7; coord1[8][1] = 1; coord1[9][0] = 3; coord1[9][1] = 3; - ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord1); + ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord1); CHECK(ret, FAIL, "H5Sselect_elements"); /* Create second dataset region */ diff --git a/test/tselect.c b/test/tselect.c index 23afc46..fae95c2 100644 --- a/test/tselect.c +++ b/test/tselect.c @@ -447,7 +447,7 @@ test_select_point(hid_t xfer_plist) coord1[7][0]=1; coord1[7][1]= 0; coord1[7][2]= 4; coord1[8][0]=2; coord1[8][1]= 1; coord1[8][2]= 6; coord1[9][0]=0; coord1[9][1]= 3; coord1[9][2]= 8; - ret = H5Sselect_elements(sid1, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord1); + ret = H5Sselect_elements(sid1, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord1); CHECK(ret, FAIL, "H5Sselect_elements"); /* Verify correct elements selected */ @@ -472,7 +472,7 @@ test_select_point(hid_t xfer_plist) coord1[7][0]=1; coord1[7][1]=14; coord1[7][2]= 6; coord1[8][0]=2; coord1[8][1]= 2; coord1[8][2]= 5; coord1[9][0]=0; coord1[9][1]= 6; coord1[9][2]=13; - ret = H5Sselect_elements(sid1, H5S_SELECT_APPEND, (size_t)POINT1_NPOINTS, coord1); + ret = H5Sselect_elements(sid1, H5S_SELECT_APPEND, (size_t)POINT1_NPOINTS, (const hsize_t *)coord1); CHECK(ret, FAIL, "H5Sselect_elements"); /* Verify correct elements selected */ @@ -497,7 +497,7 @@ test_select_point(hid_t xfer_plist) coord2[7][0]=29; coord2[7][1]= 4; coord2[8][0]= 8; coord2[8][1]= 8; coord2[9][0]=19; coord2[9][1]=17; - ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord2); + ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord2); CHECK(ret, FAIL, "H5Sselect_elements"); /* Verify correct elements selected */ @@ -526,7 +526,7 @@ test_select_point(hid_t xfer_plist) coord2[7][0]=12; coord2[7][1]= 2; coord2[8][0]=21; coord2[8][1]=12; coord2[9][0]= 9; coord2[9][1]=18; - ret = H5Sselect_elements(sid2, H5S_SELECT_PREPEND, (size_t)POINT1_NPOINTS, coord2); + ret = H5Sselect_elements(sid2, H5S_SELECT_PREPEND, (size_t)POINT1_NPOINTS, (const hsize_t *)coord2); CHECK(ret, FAIL, "H5Sselect_elements"); /* Verify correct elements selected */ @@ -568,7 +568,7 @@ test_select_point(hid_t xfer_plist) coord3[7][0]= 1; coord3[7][1]=22; coord3[8][0]=12; coord3[8][1]=21; coord3[9][0]=11; coord3[9][1]= 6; - ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord3); + ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord3); CHECK(ret, FAIL, "H5Sselect_elements"); /* Verify correct elements selected */ @@ -592,7 +592,7 @@ test_select_point(hid_t xfer_plist) coord3[7][0]= 9; coord3[7][1]=16; coord3[8][0]=12; coord3[8][1]=22; coord3[9][0]=13; coord3[9][1]= 9; - ret = H5Sselect_elements(sid2, H5S_SELECT_APPEND, (size_t)POINT1_NPOINTS, coord3); + ret = H5Sselect_elements(sid2, H5S_SELECT_APPEND, (size_t)POINT1_NPOINTS, (const hsize_t *)coord3); CHECK(ret, FAIL, "H5Sselect_elements"); /* Verify correct elements selected */ @@ -945,7 +945,7 @@ test_select_combo(void) coord1[7][0]=1; coord1[7][1]= 0; coord1[7][2]= 4; coord1[8][0]=2; coord1[8][1]= 1; coord1[8][2]= 6; coord1[9][0]=0; coord1[9][1]= 3; coord1[9][2]= 8; - ret = H5Sselect_elements(sid1, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord1); + ret = H5Sselect_elements(sid1, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord1); CHECK(ret, FAIL, "H5Sselect_elements"); /* Select 1x10 hyperslab for writing memory dataset */ @@ -1780,7 +1780,7 @@ test_select_point_copy(void) coord1[7][0]=1; coord1[7][1]= 0; coord1[7][2]= 4; coord1[8][0]=2; coord1[8][1]= 1; coord1[8][2]= 6; coord1[9][0]=0; coord1[9][1]= 3; coord1[9][2]= 8; - ret = H5Sselect_elements(sid1, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord1); + ret = H5Sselect_elements(sid1, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord1); CHECK(ret, FAIL, "H5Sselect_elements"); /* Select sequence of ten points for write dataset */ @@ -1794,7 +1794,7 @@ test_select_point_copy(void) coord2[7][0]=29; coord2[7][1]= 4; coord2[8][0]= 8; coord2[8][1]= 8; coord2[9][0]=19; coord2[9][1]=17; - ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord2); + ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord2); CHECK(ret, FAIL, "H5Sselect_elements"); /* Make a copy of the dataspace to write */ @@ -1838,7 +1838,7 @@ test_select_point_copy(void) coord3[7][0]= 1; coord3[7][1]=22; coord3[8][0]=12; coord3[8][1]=21; coord3[9][0]=11; coord3[9][1]= 6; - ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord3); + ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord3); CHECK(ret, FAIL, "H5Sselect_elements"); /* Make a copy of the dataspace to read */ @@ -2227,7 +2227,7 @@ test_select_point_offset(void) coord1[7][0]=1; coord1[7][1]= 0; coord1[7][2]= 4; coord1[8][0]=2; coord1[8][1]= 1; coord1[8][2]= 6; coord1[9][0]=0; coord1[9][1]= 3; coord1[9][2]= 8; - ret = H5Sselect_elements(sid1, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord1); + ret = H5Sselect_elements(sid1, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord1); CHECK(ret, FAIL, "H5Sselect_elements"); /* Check a valid offset */ @@ -2262,7 +2262,7 @@ test_select_point_offset(void) coord2[7][0]=23; coord2[7][1]= 4; coord2[8][0]= 8; coord2[8][1]= 8; coord2[9][0]=19; coord2[9][1]=17; - ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord2); + ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord2); CHECK(ret, FAIL, "H5Sselect_elements"); /* Choose a valid offset for the memory dataspace */ @@ -2298,7 +2298,7 @@ test_select_point_offset(void) coord3[7][0]= 1; coord3[7][1]=22; coord3[8][0]=12; coord3[8][1]=21; coord3[9][0]=11; coord3[9][1]= 6; - ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord3); + ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord3); CHECK(ret, FAIL, "H5Sselect_elements"); /* Read selection from disk */ @@ -4248,7 +4248,7 @@ test_select_point_chunk(void) points[6][1]=1; points[7][0]=6; /* In same chunk as point #3, but "earlier" in chunk */ points[7][1]=6; - ret = H5Sselect_elements(pnt1_space, H5S_SELECT_SET, (size_t)SPACE7_NPOINTS, points); + ret = H5Sselect_elements(pnt1_space, H5S_SELECT_SET, (size_t)SPACE7_NPOINTS, (const hsize_t *)points); CHECK(ret, FAIL, "H5Sselect_elements"); /* Create 1st hyperslab selection */ @@ -4284,7 +4284,7 @@ test_select_point_chunk(void) points[6][1]=2; points[7][0]=7; /* In same chunk as point #3, but "earlier" in chunk */ points[7][1]=7; - ret = H5Sselect_elements(pnt2_space, H5S_SELECT_SET, (size_t)SPACE7_NPOINTS, points); + ret = H5Sselect_elements(pnt2_space, H5S_SELECT_SET, (size_t)SPACE7_NPOINTS, (const hsize_t *)points); CHECK(ret, FAIL, "H5Sselect_elements"); /* Create 2nd hyperslab selection */ @@ -5038,7 +5038,7 @@ test_select_fill_point(hssize_t *offset) CHECK(sid1, FAIL, "H5Screate_simple"); /* Select "point" selection */ - ret = H5Sselect_elements(sid1, H5S_SELECT_SET,num_points,points); + ret = H5Sselect_elements(sid1, H5S_SELECT_SET,num_points,(const hsize_t *)points); CHECK(ret, FAIL, "H5Sselect_elements"); if(offset!=NULL) { @@ -5576,7 +5576,7 @@ test_scalar_select(void) /* Select one element in memory with a point selection */ coord1[0]=0; coord1[1]= 2; - ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)1, &coord1); + ret = H5Sselect_elements(sid2, H5S_SELECT_SET, (size_t)1, (const hsize_t *)&coord1); CHECK(ret, FAIL, "H5Sselect_elements"); /* Write single point to disk */ @@ -5695,7 +5695,7 @@ test_scalar_select2(void) /* Select one element in memory with a point selection */ coord1[0]=0; H5E_BEGIN_TRY { - ret = H5Sselect_elements(sid, H5S_SELECT_SET, (size_t)1, &coord1); + ret = H5Sselect_elements(sid, H5S_SELECT_SET, (size_t)1, (const hsize_t *)&coord1); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Sselect_elements"); @@ -5763,7 +5763,7 @@ test_scalar_select3(void) /* Select one element in file with a point selection */ coord1[0] = 0; coord1[1] = 2; - ret = H5Sselect_elements(sid1, H5S_SELECT_SET, (size_t)1, &coord1); + ret = H5Sselect_elements(sid1, H5S_SELECT_SET, (size_t)1, (const hsize_t *)&coord1); CHECK(ret, FAIL, "H5Sselect_elements"); /* Write single point to disk */ @@ -5924,7 +5924,7 @@ test_shape_same(void) /* Select sequence of ten points for multiple point selection */ coord1[0][0] = 2; coord1[0][1] = 2; - ret = H5Sselect_elements(single_pt_sid, H5S_SELECT_SET, (size_t)1, coord1); + ret = H5Sselect_elements(single_pt_sid, H5S_SELECT_SET, (size_t)1, (const hsize_t *)coord1); CHECK(ret, FAIL, "H5Sselect_elements"); /* Create dataspace for multiple point selection */ @@ -5942,7 +5942,7 @@ test_shape_same(void) coord2[7][0]=1; coord2[7][1]=0; coord2[8][0]=5; coord2[8][1]=1; coord2[9][0]=9; coord2[9][1]=3; - ret = H5Sselect_elements(mult_pt_sid, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, coord2); + ret = H5Sselect_elements(mult_pt_sid, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord2); CHECK(ret, FAIL, "H5Sselect_elements"); /* Create dataspace for single hyperslab selection */ @@ -6623,7 +6623,7 @@ test_shape_same(void) for(v=0; v<2; v++) { coord2[v][0]=u; coord2[v][1]=(v*2)+2; } /* end for */ - ret = H5Sselect_elements(tmp_sid, H5S_SELECT_APPEND, (size_t)2, coord2); + ret = H5Sselect_elements(tmp_sid, H5S_SELECT_APPEND, (size_t)2, (const hsize_t *)coord2); CHECK(ret, FAIL, "H5Sselect_elements"); } /* end for */ @@ -7975,7 +7975,7 @@ test_select_bounds(void) coord[1][0]= 3; coord[1][1]= 96; coord[2][0]= 96; coord[2][1]= 3; coord[3][0]= 96; coord[3][1]= 96; - ret = H5Sselect_elements(sid, H5S_SELECT_SET, (size_t)SPACE11_NPOINTS, coord); + ret = H5Sselect_elements(sid, H5S_SELECT_SET, (size_t)SPACE11_NPOINTS, (const hsize_t *)coord); CHECK(ret, FAIL, "H5Sselect_elements"); /* Get bounds for point selection */ diff --git a/test/tskiplist.c b/test/tskiplist.c index 6f56c39..289df0b 100644 --- a/test/tskiplist.c +++ b/test/tskiplist.c @@ -1165,6 +1165,164 @@ test_skiplist_greater(void) /**************************************************************** ** +** test_skiplist_below(): Test H5SL (skip list) code. +** Tests 'below' operation in skip lists. +** +****************************************************************/ +static void +test_skiplist_below(void) +{ + H5SL_t *slist; /* Skip list created */ + H5SL_node_t *node; /* Skip list node */ + size_t u; /* Local index variable */ + unsigned data[10]={ 10, 20, 15, 5, 50, 30, 31, 32, 80, 90}; + /* unsigned sorted_data[10]={ 5, 10, 15, 20, 30, 31, 32, 50, 80, 90}; */ + unsigned *found_item; /* Item found in skip list */ + unsigned find_item; /* Item to add to skip list */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(7, ("Testing Skip List 'Less' Operation\n")); + + /* Create a skip list */ + slist = H5SL_create(H5SL_TYPE_UNSIGNED, 0.5, (size_t)16); + CHECK(slist, NULL, "H5SL_create"); + + /* Insert objects into the skip list */ + for(u = 0; u < 10; u++) { + ret = H5SL_insert(slist, &data[u], &data[u]); + CHECK(ret, FAIL, "H5SL_insert"); + } /* end for */ + + /* Check for exact match of items in various positions */ + find_item = 20; + node = H5SL_below(slist, &find_item); + CHECK(node, NULL, "H5SL_below"); + found_item = H5SL_item(node); + VERIFY(*found_item, find_item, "H5SL_below"); + find_item = 90; + node = H5SL_below(slist, &find_item); + CHECK(node, NULL, "H5SL_below"); + found_item = H5SL_item(node); + VERIFY(*found_item, find_item, "H5SL_below"); + find_item = 5; + node = H5SL_below(slist, &find_item); + CHECK(node, NULL, "H5SL_below"); + found_item = H5SL_item(node); + VERIFY(*found_item, find_item, "H5SL_below"); + + /* Find item less than a missing key, in various positions */ + find_item = 19; + node = H5SL_below(slist, &find_item); + CHECK(node, NULL, "H5SL_below"); + found_item = H5SL_item(node); + VERIFY(*found_item, 15, "H5SL_below"); + find_item = 89; + node = H5SL_below(slist, &find_item); + CHECK(node, NULL, "H5SL_below"); + found_item = H5SL_item(node); + VERIFY(*found_item, 80, "H5SL_below"); + find_item = 100; + node = H5SL_below(slist, &find_item); + CHECK(node, NULL, "H5SL_below"); + found_item = H5SL_item(node); + VERIFY(*found_item, 90, "H5SL_below"); + find_item = 9; + node = H5SL_below(slist, &find_item); + CHECK(node, NULL, "H5SL_below"); + found_item = H5SL_item(node); + VERIFY(*found_item, 5, "H5SL_below"); + find_item = 4; + node = H5SL_less(slist, &find_item); + VERIFY(node, NULL, "H5SL_below"); + + /* Close the skip list */ + ret = H5SL_close(slist); + CHECK(ret, FAIL, "H5SL_close"); + +} /* end test_skiplist_below() */ + +/**************************************************************** +** +** test_skiplist_above(): Test H5SL (skip list) code. +** Tests 'above' operation in skip lists. +** +****************************************************************/ +static void +test_skiplist_above(void) +{ + H5SL_t *slist; /* Skip list created */ + H5SL_node_t *node; /* Skip list node */ + size_t u; /* Local index variable */ + unsigned data[10]={ 10, 20, 15, 5, 50, 30, 31, 32, 80, 90}; + /* unsigned sorted_data[10]={ 5, 10, 15, 20, 30, 31, 32, 50, 80, 90}; */ + unsigned *found_item; /* Item found in skip list */ + unsigned find_item; /* Item to add to skip list */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(7, ("Testing Skip List 'Greater' Operation\n")); + + /* Create a skip list */ + slist = H5SL_create(H5SL_TYPE_UNSIGNED, 0.5, (size_t)16); + CHECK(slist, NULL, "H5SL_create"); + + /* Insert objects into the skip list */ + for(u = 0; u < 10; u++) { + ret = H5SL_insert(slist, &data[u], &data[u]); + CHECK(ret, FAIL, "H5SL_insert"); + } /* end for */ + + /* Check for exact match of items in various positions */ + find_item = 20; + node = H5SL_above(slist, &find_item); + CHECK(node, NULL, "H5SL_above"); + found_item = H5SL_item(node); + VERIFY(*found_item, find_item, "H5SL_above"); + find_item = 90; + node = H5SL_above(slist, &find_item); + CHECK(node, NULL, "H5SL_above"); + found_item = H5SL_item(node); + VERIFY(*found_item, find_item, "H5SL_above"); + find_item = 5; + node = H5SL_above(slist, &find_item); + CHECK(node, NULL, "H5SL_above"); + found_item = H5SL_item(node); + VERIFY(*found_item, find_item, "H5SL_above"); + + /* Find item greater than a missing key, in various positions */ + find_item = 19; + node = H5SL_above(slist, &find_item); + CHECK(node, NULL, "H5SL_above"); + found_item = H5SL_item(node); + VERIFY(*found_item, 20, "H5SL_above"); + find_item = 89; + node = H5SL_above(slist, &find_item); + CHECK(node, NULL, "H5SL_above"); + found_item = H5SL_item(node); + VERIFY(*found_item, 90, "H5SL_above"); + find_item = 100; + node = H5SL_above(slist, &find_item); + VERIFY(node, NULL, "H5SL_above"); + find_item = 6; + node = H5SL_above(slist, &find_item); + CHECK(node, NULL, "H5SL_above"); + found_item = H5SL_item(node); + VERIFY(*found_item, 10, "H5SL_above"); + find_item = 4; + node = H5SL_above(slist, &find_item); + CHECK(node, NULL, "H5SL_above"); + found_item = H5SL_item(node); + VERIFY(*found_item, 5, "H5SL_above"); + + /* Close the skip list */ + ret = H5SL_close(slist); + CHECK(ret, FAIL, "H5SL_close"); + +} /* end test_skiplist_above() */ + +/**************************************************************** +** ** test_skiplist_remote_first(): Test H5SL (skip list) code. ** Tests 'remove first' operation in skip lists. ** @@ -1240,7 +1398,9 @@ test_skiplist(void) test_skiplist_free(); /* Test 'free' operation */ test_skiplist_less(); /* Test 'less' operation */ test_skiplist_greater(); /* Test 'greater' operation */ - test_skiplist_remove_first(); /* Test 'remove first' operation */ + test_skiplist_below(); /* Test 'below' operation */ + test_skiplist_above(); /* Test 'above' operation */ + test_skiplist_remove_first(); /* Test 'remove first' operation */ } /* end test_skiplist() */ @@ -212,10 +212,11 @@ test_direct(void) if(H5Fget_filesize(file, &file_size) < 0) TEST_ERROR; - /* There is no garantee the size of metadata in file is constant. - * Just try to check if it's reasonable. It's 2KB right now. + /* There is no guarantee of the number of metadata allocations, but it's + * 4 currently and the size of the file should be between 3 & 4 file buffer + * sizes.. */ - if(file_size<1*KB || file_size>4*KB) + if(file_size < (FBSIZE * 3) || file_size >= (FBSIZE * 4)) TEST_ERROR; /* Allocate aligned memory for data set 1. For data set 1, everything is aligned including diff --git a/testpar/t_cache.c b/testpar/t_cache.c index 0a7cb72..c858e9b 100644 --- a/testpar/t_cache.c +++ b/testpar/t_cache.c @@ -2180,7 +2180,7 @@ expunge_entry(H5C_t * cache_ptr, if ( nerrors == 0 ) { result = H5AC_expunge_entry(file_ptr, -1, &(types[0]), - entry_ptr->header.addr); + entry_ptr->header.addr, H5AC__NO_FLAGS_SET); if ( result < 0 ) { |