static herr_t H5SM_convert_list_to_btree(H5F_t * f, H5SM_index_header_t * header,
                H5SM_list_t **_list, H5HF_t *fheap, H5O_t *open_oh, hid_t dxpl_id);
static herr_t H5SM_convert_btree_to_list(H5F_t * f, H5SM_index_header_t * header, hid_t dxpl_id);
static herr_t H5SM_incr_ref(void *record, void *_op_data, hbool_t *changed);
static herr_t H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
    H5SM_index_header_t *header, hbool_t defer, unsigned type_id, void *mesg,
    unsigned *cache_flags_ptr);
static herr_t H5SM_decr_ref(void *record, void *op_data, hbool_t *changed);
static herr_t H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
    H5SM_index_header_t *header, const H5O_shared_t * mesg,
    unsigned *cache_flags, void ** /*out*/ encoded_mesg);
    unsigned *cache_flags, size_t * /*out*/ mesg_size, void ** /*out*/ encoded_mesg);
static herr_t H5SM_type_to_flag(unsigned type_id, unsigned *type_flag);
static herr_t H5SM_read_iter_op(H5O_t *oh, H5O_mesg_t *mesg, unsigned sequence,
    unsigned *oh_modified, void *_udata);
static herr_t H5SM_read_mesg_fh_cb(const void *obj, size_t obj_len, void *_udata);
static herr_t H5SM_read_mesg(H5F_t *f, const H5SM_sohm_t *mesg, H5HF_t *fheap,
               H5O_t * open_oh, hid_t dxpl_id, size_t *encoding_size /*out*/,
               void ** encoded_mesg /*out*/);
/*********************/
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5SM_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_shared_t *sh_mesg)
{
    H5SM_master_table_t  *table = NULL;
    unsigned              cache_flags = H5AC__NO_FLAGS_SET;
    H5SM_table_cache_ud_t cache_udata;      /* User-data for callback */
    ssize_t               index_num;
    size_t                mesg_size = 0;
    void                 *mesg_buf = NULL;
    void                 *native_mesg = NULL;
    unsigned              type_id;              /* Message type ID to operate on */
    herr_t                ret_value = SUCCEED;
    FUNC_ENTER_NOAPI(FAIL)
    HDassert(f);
    HDassert(H5F_addr_defined(H5F_SOHM_ADDR(f)));
    HDassert(sh_mesg);
    HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
    /* Find the correct index and try to delete from it */
    if((index_num = H5SM_get_index(table, type_id)) < 0)
    HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "unable to find correct SOHM index")
    /* If mesg_buf is not NULL, the message's reference count has reached
     * zero and any file space it uses needs to be freed.  mesg_buf holds the
     * serialized form of the message.
     */
    if(H5SM_delete_from_index(f, dxpl_id, open_oh, &(table->indexes[index_num]), sh_mesg, &cache_flags, &mesg_buf) < 0)
    HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete mesage from SOHM index")
    if(H5SM_delete_from_index(f, dxpl_id, open_oh, &(table->indexes[index_num]), sh_mesg, &cache_flags, &mesg_size, &mesg_buf) < 0)
        HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete mesage from SOHM index")
    /* Release the master SOHM table */
    if(H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, cache_flags) < 0)
    HGOTO_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
    table = NULL;
    /* If buf was allocated, delete the message it holds.  This message may
     * reference other shared messages that also need to be deleted, so the
     * master table needs to be unprotected when we do this.
     */
    if(mesg_buf) {
        if(NULL == (native_mesg = H5O_msg_decode(f, dxpl_id, open_oh, type_id, (const unsigned char *)mesg_buf)))
        if(NULL == (native_mesg = H5O_msg_decode(f, dxpl_id, open_oh, type_id, mesg_size, (const unsigned char *)mesg_buf)))
            HGOTO_ERROR(H5E_SOHM, H5E_CANTDECODE, FAIL, "can't decode shared message.")
        if(H5O_msg_delete(f, dxpl_id, open_oh, type_id, native_mesg) < 0)
            HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "can't delete shared message.")
    } /* end if */
done:
    /* Release the master SOHM table (should only happen on error) */
    if(table && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, cache_flags) < 0)
    HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
 *              Negative on failure
 *
 * Programmer:  James Laird
 *              Tuesday, May 2, 2006
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
    H5SM_index_header_t *header, const H5O_shared_t *mesg,
    unsigned *cache_flags, void ** /*out*/ encoded_mesg)
    unsigned *cache_flags, size_t * /*out*/ mesg_size, void ** /*out*/ encoded_mesg)
{
    H5SM_list_t     *list = NULL;
    H5SM_mesg_key_t key;
    H5SM_sohm_t     message;            /* Deleted message returned from index */
    H5SM_sohm_t    *message_ptr;        /* Pointer to deleted message returned from index */
    H5HF_t         *fheap = NULL;       /* Fractal heap that contains the message */
    H5B2_t         *bt2 = NULL;         /* v2 B-tree handle for index */
    size_t          buf_size;           /* Size of the encoded message (out) */
    void            *encoding_buf = NULL; /* The encoded message (out) */
    unsigned        type_id;            /* Message type to operate on */
        } /* end else */
        /* Remove the message from the heap if it was stored in the heap*/
        if(old_loc == H5SM_IN_HEAP)
            if(H5HF_remove(fheap, dxpl_id, &(message_ptr->u.heap_loc.fheap_id)) < 0)
            HGOTO_ERROR(H5E_SOHM, H5E_CANTREMOVE, FAIL, "unable to remove message from heap")
        /* Return the message's encoding so anything it references can be freed */
        *encoded_mesg = encoding_buf;
        *mesg_size = buf_size;
        /* If there are no messages left in the index, delete it */
        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 | H5AC__FREE_FILE_SPACE_FLAG) < 0)
            HGOTO_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to release SOHM list")
            list = NULL;
            HDassert(fheap);
    /* Release the fractal heap & v2 B-tree if we opened them */
    if(fheap && H5HF_close(fheap, dxpl_id) < 0)
        HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close fractal heap")
    if(bt2 && H5B2_close(bt2, dxpl_id) < 0)
        HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for SOHM index")
    /* Free the message encoding, if we're not returning it in encoded_mesg
     * or if there's been an error.
     */
    if(encoding_buf && (NULL == *encoded_mesg || ret_value < 0))
    if(encoding_buf && (NULL == *encoded_mesg || ret_value < 0)) {
        encoding_buf = H5MM_xfree(encoding_buf);
        *mesg_size = 0;
    }
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5SM_delete_from_index() */
/*-------------------------------------------------------------------------
 * Function:    H5SM_get_info
 *
 * Purpose:     Get the shared message info for a file, if there is any.
 *