diff options
Diffstat (limited to 'src/H5Otest.c')
-rw-r--r-- | src/H5Otest.c | 747 |
1 files changed, 747 insertions, 0 deletions
diff --git a/src/H5Otest.c b/src/H5Otest.c new file mode 100644 index 0000000..f0deade --- /dev/null +++ b/src/H5Otest.c @@ -0,0 +1,747 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Programmer: Quincey Koziol <koziol@hdfgroup.org> + * Monday, December 4, 2006 + * + * Purpose: Object header testing functions. + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5A_FRIEND /*suppress error about including H5Apkg */ +#include "H5Omodule.h" /* This source code file is part of the H5O module */ +#define H5O_TESTING /*suppress warning about H5O testing funcs*/ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Apkg.h" /* Attributes */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Opkg.h" /* Object headers */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + +/*-------------------------------------------------------------------------- + NAME + H5O_is_attr_dense_test + PURPOSE + Determine whether attributes for an object are stored "densely" + USAGE + htri_t H5O_is_attr_dense_test(oid) + hid_t oid; IN: object to check + RETURNS + Non-negative TRUE/FALSE on success, negative on failure + DESCRIPTION + Checks to see if the object is storing attributes in the "dense" or + "compact" form. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +htri_t +H5O_is_attr_dense_test(hid_t oid) +{ + H5O_t *oh = NULL; /* Object header */ + H5O_ainfo_t ainfo; /* Attribute information for object */ + H5O_loc_t *loc; /* Pointer to object's location */ + htri_t ret_value = FAIL; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Get object location for object */ + if(NULL == (loc = H5O_get_loc(oid))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") + + /* Get the object header */ + if(NULL == (oh = H5O_protect(loc, H5AC_ind_read_dxpl_id, H5AC__READ_ONLY_FLAG, FALSE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") + + /* Check for attribute info stored */ + ainfo.fheap_addr = HADDR_UNDEF; + if(oh->version > H5O_VERSION_1) { + /* Check for (& retrieve if available) attribute info */ + if(H5A_get_ainfo(loc->file, H5AC_ind_read_dxpl_id, oh, &ainfo) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message") + } /* end if */ + + /* Check if dense storage is being used */ + if(H5F_addr_defined(ainfo.fheap_addr)) { + /* Check for any messages in object header */ + HDassert(H5O_msg_count_real(oh, H5O_MSG_ATTR) == 0); + + ret_value = TRUE; + } /* end if */ + else + ret_value = FALSE; + +done: + if(oh && H5O_unprotect(loc, H5AC_ind_read_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_is_attr_dense_test() */ + + +/*-------------------------------------------------------------------------- + NAME + H5O_is_attr_empty_test + PURPOSE + Determine whether there are any attributes for an object + USAGE + htri_t H5O_is_attr_empty_test(oid) + hid_t oid; IN: object to check + RETURNS + Non-negative TRUE/FALSE on success, negative on failure + DESCRIPTION + Checks to see if the object is storing any attributes. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +htri_t +H5O_is_attr_empty_test(hid_t oid) +{ + H5O_t *oh = NULL; /* Object header */ + H5B2_t *bt2_name = NULL; /* v2 B-tree handle for name index */ + H5O_ainfo_t ainfo; /* Attribute information for object */ + htri_t ainfo_exists = FALSE; /* Whether the attribute info exists in the file */ + H5O_loc_t *loc; /* Pointer to object's location */ + hsize_t nattrs; /* Number of attributes */ + htri_t ret_value = FAIL; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Get object location for object */ + if(NULL == (loc = H5O_get_loc(oid))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") + + /* Get the object header */ + if(NULL == (oh = H5O_protect(loc, H5AC_ind_read_dxpl_id, H5AC__READ_ONLY_FLAG, FALSE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") + + /* Check for attribute info stored */ + if(oh->version > H5O_VERSION_1) { + /* Check for (& retrieve if available) attribute info */ + if((ainfo_exists = H5A_get_ainfo(loc->file, H5AC_ind_read_dxpl_id, oh, &ainfo)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message") + } /* end if */ + + /* Retrieve the number of attribute messages in header */ + nattrs = H5O_msg_count_real(oh, H5O_MSG_ATTR); + + /* Check for later version of object header format & attribute info available */ + if(oh->version > H5O_VERSION_1) { + if(ainfo_exists) { + /* Check for using dense storage */ + if(H5F_addr_defined(ainfo.fheap_addr)) { + /* Check for any messages in object header */ + HDassert(nattrs == 0); + + /* Set metadata tag in dxpl_id */ + H5_BEGIN_TAG(H5AC_ind_read_dxpl_id, loc->addr, FAIL); + + /* Open the name index v2 B-tree */ + if(NULL == (bt2_name = H5B2_open(loc->file, H5AC_ind_read_dxpl_id, ainfo.name_bt2_addr, NULL))) + HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index") + + /* Reset metadata tag in dxpl_id */ + H5_END_TAG(FAIL); + + /* Retrieve # of records in name index */ + if(H5B2_get_nrec(bt2_name, &nattrs) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, FAIL, "unable to retrieve # of records from name index") + } /* end if */ + + /* Verify that attribute count in object header is correct */ + HDassert(nattrs == ainfo.nattrs); + } /* end if */ + else + HDassert(nattrs == 0); + } /* end if */ + + /* Set the return value */ + ret_value = (nattrs == 0) ? TRUE : FALSE; + +done: + /* Release resources */ + if(bt2_name && H5B2_close(bt2_name, H5AC_ind_read_dxpl_id) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for name index") + if(oh && H5O_unprotect(loc, H5AC_ind_read_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_is_attr_empty_test() */ + + +/*-------------------------------------------------------------------------- + NAME + H5O_num_attrs_test + PURPOSE + Determine whether there are any attributes for an object + USAGE + herr_t H5O_num_attrs_test(oid, nattrs) + hid_t oid; IN: object to check + hsize_t *nattrs; OUT: Number of attributes on object + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Checks the # of attributes on an object + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5O_num_attrs_test(hid_t oid, hsize_t *nattrs) +{ + H5O_t *oh = NULL; /* Object header */ + H5B2_t *bt2_name = NULL; /* v2 B-tree handle for name index */ + H5O_ainfo_t ainfo; /* Attribute information for object */ + H5O_loc_t *loc; /* Pointer to object's location */ + hsize_t obj_nattrs; /* Number of attributes */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Get object location for object */ + if(NULL == (loc = H5O_get_loc(oid))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") + + /* Get the object header */ + if(NULL == (oh = H5O_protect(loc, H5AC_ind_read_dxpl_id, H5AC__READ_ONLY_FLAG, FALSE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") + + /* Check for attribute info stored */ + ainfo.fheap_addr = HADDR_UNDEF; + if(oh->version > H5O_VERSION_1) { + /* Check for (& retrieve if available) attribute info */ + if(H5A_get_ainfo(loc->file, H5AC_ind_read_dxpl_id, oh, &ainfo) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message") + } /* end if */ + + /* Retrieve the number of attribute messages in header */ + obj_nattrs = H5O_msg_count_real(oh, H5O_MSG_ATTR); + + /* Check for later version of object header format */ + if(oh->version > H5O_VERSION_1) { + /* Check for using dense storage */ + if(H5F_addr_defined(ainfo.fheap_addr)) { + /* Check for any messages in object header */ + HDassert(obj_nattrs == 0); + + /* Set metadata tag in dxpl_id */ + H5_BEGIN_TAG(H5AC_ind_read_dxpl_id, loc->addr, FAIL); + + /* Open the name index v2 B-tree */ + if(NULL == (bt2_name = H5B2_open(loc->file, H5AC_ind_read_dxpl_id, ainfo.name_bt2_addr, NULL))) + HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index") + + /* Reset metadata tag in dxpl_id */ + H5_END_TAG(FAIL); + + /* Retrieve # of records in name index */ + if(H5B2_get_nrec(bt2_name, &obj_nattrs) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, FAIL, "unable to retrieve # of records from name index") + } /* end if */ + + /* Verify that attribute count in object header is correct */ + HDassert(obj_nattrs == ainfo.nattrs); + } /* end if */ + + /* Set the number of attributes */ + *nattrs = obj_nattrs; + +done: + /* Release resources */ + if(bt2_name && H5B2_close(bt2_name, H5AC_ind_read_dxpl_id) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for name index") + if(oh && H5O_unprotect(loc, H5AC_ind_read_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_num_attrs_test() */ + + +/*-------------------------------------------------------------------------- + NAME + H5O_attr_dense_info_test + PURPOSE + Retrieve information about the state of the "dense" storage for attributes + USAGE + herr_t H5O_attr_dense_info_test(oid, name_count, corder_count) + hid_t oid; IN: Object to check + hsize_t *name_count; OUT: Number of attributes in name index + hsize_t *corder_count; OUT: Number of attributes in creation order index + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Currently, just retrieves the number of attributes in each index and returns + them. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5O_attr_dense_info_test(hid_t oid, hsize_t *name_count, hsize_t *corder_count) +{ + H5O_t *oh = NULL; /* Object header */ + H5B2_t *bt2_name = NULL; /* v2 B-tree handle for name index */ + H5B2_t *bt2_corder = NULL; /* v2 B-tree handle for creation order index */ + H5O_ainfo_t ainfo; /* Attribute information for object */ + H5O_loc_t *loc; /* Pointer to object's location */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Get object location for object */ + if(NULL == (loc = H5O_get_loc(oid))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") + + /* Set metadata tag in dxpl_id */ + H5_BEGIN_TAG(H5AC_ind_read_dxpl_id, loc->addr, FAIL); + + /* Get the object header */ + if(NULL == (oh = H5O_protect(loc, H5AC_ind_read_dxpl_id, H5AC__READ_ONLY_FLAG, FALSE))) + HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") + + /* Check for attribute info stored */ + ainfo.fheap_addr = HADDR_UNDEF; + if(oh->version > H5O_VERSION_1) { + /* Check for (& retrieve if available) attribute info */ + if(H5A_get_ainfo(loc->file, H5AC_ind_read_dxpl_id, oh, &ainfo) < 0) + HGOTO_ERROR_TAG(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message") + } /* end if */ + + /* Check for 'dense' attribute storage file addresses being defined */ + if(!H5F_addr_defined(ainfo.fheap_addr)) + HGOTO_DONE_TAG(FAIL, FAIL) + if(!H5F_addr_defined(ainfo.name_bt2_addr)) + HGOTO_DONE_TAG(FAIL, FAIL) + + /* Open the name index v2 B-tree */ + if(NULL == (bt2_name = H5B2_open(loc->file, H5AC_ind_read_dxpl_id, ainfo.name_bt2_addr, NULL))) + HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index") + + /* Retrieve # of records in name index */ + if(H5B2_get_nrec(bt2_name, name_count) < 0) + HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTCOUNT, FAIL, "unable to retrieve # of records from name index") + + /* Check if there is a creation order index */ + if(H5F_addr_defined(ainfo.corder_bt2_addr)) { + /* Open the creation order index v2 B-tree */ + if(NULL == (bt2_corder = H5B2_open(loc->file, H5AC_ind_read_dxpl_id, ainfo.corder_bt2_addr, NULL))) + HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index") + + /* Retrieve # of records in creation order index */ + if(H5B2_get_nrec(bt2_corder, corder_count) < 0) + HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTCOUNT, FAIL, "unable to retrieve # of records from creation order index") + } /* end if */ + else + *corder_count = 0; + + /* Reset metadata tag in dxpl_id */ + H5_END_TAG(FAIL); + +done: + /* Release resources */ + if(bt2_name && H5B2_close(bt2_name, H5AC_ind_read_dxpl_id) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for name index") + if(bt2_corder && H5B2_close(bt2_corder, H5AC_ind_read_dxpl_id) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for creation order index") + if(oh && H5O_unprotect(loc, H5AC_ind_read_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_attr_dense_info_test() */ + + +/*-------------------------------------------------------------------------- + NAME + H5O_check_msg_marked_test + PURPOSE + Check if an unknown message with the "mark if unknown" flag actually gets + marked. + USAGE + herr_t H5O_check_msg_marked_test(oid, flag_val) + hid_t oid; IN: Object to check + hbool_t flag_val; IN: Desired flag value + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Locates the "unknown" message and checks that the "was unknown" flag is set + correctly. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5O_check_msg_marked_test(hid_t oid, hbool_t flag_val) +{ + H5O_t *oh = NULL; /* Object header */ + H5O_loc_t *loc; /* Pointer to object's location */ + H5O_mesg_t *idx_msg; /* Pointer to message */ + unsigned idx; /* Index of message */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Get object location for object */ + if(NULL == (loc = H5O_get_loc(oid))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") + + /* Get the object header */ + if(NULL == (oh = H5O_protect(loc, H5AC_ind_read_dxpl_id, H5AC__READ_ONLY_FLAG, FALSE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") + + /* Locate "unknown" message */ + for(idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++) + if(idx_msg->type->id == H5O_UNKNOWN_ID) { + /* Check for "unknown" message having the correct flags */ + if(((idx_msg->flags & H5O_MSG_FLAG_WAS_UNKNOWN) > 0) != flag_val) + HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "'unknown' message has incorrect 'was unknown' flag value") + + /* Break out of loop, to indicate that the "unknown" message was found */ + break; + } /* end if */ + + /* Check for not finding an "unknown" message */ + if(idx == oh->nmesgs) + HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "'unknown' message type not found") + +done: + if(oh && H5O_unprotect(loc, H5AC_ind_read_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_check_msg_marked_test() */ + + +/*-------------------------------------------------------------------------- + NAME + H5O_expunge_chunks_test + PURPOSE + Expunge all the chunks for an object header from the cache. + USAGE + herr_t H5O_expunge_chunks_test(f, dxpl_id, loc) + H5F_t *f; IN: Pointer to file that object is within + hid_t dxpl_id; IN: DXPL to use for operation + H5O_loc_t *loc; IN: Object location for object header to expunge + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Iterates over all the chunks for an object header an expunges each from the + metadata cache. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5O_expunge_chunks_test(const H5O_loc_t *loc, hid_t dxpl_id) +{ + H5O_t *oh = NULL; /* Object header */ + haddr_t chk_addr[16]; /* Array of chunk addresses */ + size_t nchunks; /* Number of chunks in object header */ + size_t u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Get the object header */ + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__NO_FLAGS_SET, FALSE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header") + + /* Safety check */ + nchunks = oh->nchunks; + HDassert(0 < nchunks && nchunks < NELMTS(chk_addr)); + + /* Iterate over all the chunks, saving the chunk addresses */ + for(u = 0; u < oh->nchunks; u++) + chk_addr[u] = oh->chunk[u].addr; + + /* Release the object header */ + if(H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header") + + /* Iterate over all the saved chunk addresses, evicting them from the cache */ + /* (in reverse order, so that chunk #0 is unpinned) */ + for(u = nchunks - 1; u < nchunks; u--) + if(H5AC_expunge_entry(loc->file, dxpl_id, (u == 0 ? H5AC_OHDR : H5AC_OHDR_CHK), chk_addr[u], H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTEXPUNGE, FAIL, "unable to expunge object header chunk") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_expunge_chunks_test() */ + + +/*-------------------------------------------------------------------------- + NAME + H5O_get_rc + PURPOSE + Retrieve the refcount for the object header + USAGE + herr_t H5O_expunge_chunks_test(loc, dxpl_id, rc) + const H5O_loc_t *loc; IN: Object location for object header to query + hid_t dxpl_id; IN: DXPL to use for operation + unsigned *rc; OUT: Pointer to refcount for object header + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Protects object header, retrieves the object header's refcount, and + unprotects object header. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5O_get_rc(const H5O_loc_t *loc, hid_t dxpl_id, unsigned *rc) +{ + H5O_t *oh = NULL; /* Object header */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity check */ + HDassert(loc); + HDassert(rc); + + /* Get the object header */ + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header") + + /* Save the refcount for the object header */ + *rc = oh->nlink; + +done: + /* Release the object header */ + if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_expunge_chunks_test() */ + + +/*-------------------------------------------------------------------------- + NAME + H5O_msg_get_chunkno_test + PURPOSE + Retrieve the chunk number for an object header message of a given type. + USAGE + herr_t H5O_check_msg_marked_test(oid, chunk_num) + hid_t oid; IN: Object to check + unsigned msg_type; IN: Object header message type to check + unsigned *chunk_num; OUT: Object header chunk that the message is in + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Retrieves the chunk number for the first object header message of a given + type found in an object's header. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5O_msg_get_chunkno_test(hid_t oid, unsigned msg_type, unsigned *chunk_num) +{ + H5O_t *oh = NULL; /* Object header */ + H5O_loc_t *loc; /* Pointer to object's location */ + H5O_mesg_t *idx_msg; /* Pointer to message */ + unsigned idx; /* Index of message */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Get object location for object */ + if(NULL == (loc = H5O_get_loc(oid))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") + + /* Get the object header */ + if(NULL == (oh = H5O_protect(loc, H5AC_ind_read_dxpl_id, H5AC__READ_ONLY_FLAG, FALSE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") + + /* Locate first message of given type */ + for(idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++) + if(idx_msg->type->id == msg_type) { + /* Set the chunk number for the message */ + *chunk_num = idx_msg->chunkno; + + /* Break out of loop, to indicate that the message was found */ + break; + } /* end if */ + + /* Check for not finding a message of the given type*/ + if(idx == oh->nmesgs) + HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message of type not found") + +done: + if(oh && H5O_unprotect(loc, H5AC_ind_read_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_msg_get_chunkno_test() */ + + +/*-------------------------------------------------------------------------- + NAME + H5O_msg_move_to_new_chunk_test + PURPOSE + Move a message into a new chunk + USAGE + herr_t H5O_msg_move_to_new_chunk_test(oid, msg_type) + hid_t oid; IN: Object to check + unsigned msg_type; IN: Object header message type to check + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Moves the first message of the given type to a new object header chunk. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5O_msg_move_to_new_chunk_test(hid_t oid, unsigned msg_type) +{ + H5O_t *oh = NULL; /* Object header */ + H5O_loc_t *loc; /* Pointer to object's location */ + H5O_mesg_t *curr_msg; /* Pointer to current message */ + unsigned idx; /* Index of message */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Get object location for object */ + if(NULL == (loc = H5O_get_loc(oid))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") + + /* Get the object header */ + if(NULL == (oh = H5O_protect(loc, H5AC_ind_read_dxpl_id, H5AC__NO_FLAGS_SET, FALSE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header") + + /* Locate first message of given type */ + for(idx = 0, curr_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, curr_msg++) + if(curr_msg->type->id == msg_type) { + H5O_msg_alloc_info_t found_msg; /* Information about message to move */ + unsigned msg_chunkno = curr_msg->chunkno; /* Chunk that the message is in */ + uint8_t *end_chunk_data = (oh->chunk[msg_chunkno].image + oh->chunk[msg_chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[msg_chunkno].gap); /* End of message data in chunk */ + uint8_t *end_msg = curr_msg->raw + curr_msg->raw_size; /* End of current message */ + size_t gap_size = 0; /* Size of gap after current message */ + size_t null_size = 0; /* Size of NULL message after current message */ + unsigned null_msgno = 0; /* Index of NULL message after current message */ + size_t total_size; /* Total size of available space "around" current message */ + size_t new_idx; /* Index of new null message */ + + /* Check if the message is the last one in the chunk */ + if(end_msg == end_chunk_data) + gap_size = oh->chunk[msg_chunkno].gap; + else { + H5O_mesg_t *tmp_msg; /* Temp. pointer to message to operate on */ + unsigned v; /* Local index variable */ + + /* Check for null message after this message, in same chunk */ + for(v = 0, tmp_msg = &oh->mesg[0]; v < oh->nmesgs; v++, tmp_msg++) { + if(tmp_msg->type->id == H5O_NULL_ID && (tmp_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh)) == end_msg) { + null_msgno = v; + null_size = (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + tmp_msg->raw_size; + break; + } /* end if */ + + /* XXX: Should also check for NULL message in front of current message... */ + + } /* end for */ + } /* end else */ + + /* Add up current message's total available space */ + total_size = curr_msg->raw_size + gap_size + null_size; + + /* Set up "found message" info for moving the message */ + found_msg.msgno = (int)idx; + found_msg.id = curr_msg->type->id; + found_msg.chunkno = msg_chunkno; + found_msg.gap_size = gap_size; + found_msg.null_size = null_size; + found_msg.total_size = total_size; + found_msg.null_msgno = null_msgno; + + /* Allocate and initialize new chunk in the file, moving the found message */ + /* (*new_idx returned from this routine is unused here) */ + if(H5O__alloc_chunk(loc->file, H5AC_ind_read_dxpl_id, oh, 40, oh->nmesgs, &found_msg, &new_idx) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "can't allocate new object header chunk") + + /* Break out of loop, the message was found */ + break; + } /* end if */ + +done: + if(oh && H5O_unprotect(loc, H5AC_ind_read_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_msg_get_chunkno_test() */ + |