mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-03-19 16:50:46 +08:00
This reverts commit 4242753848c44ab3b5d226e66225eac2f64db314, reversing changes made to b0e79fe6dd20ec7aa1b3e5f0f8b370639a4ef5bd.
2306 lines
76 KiB
C
2306 lines
76 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
* 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. *
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
||
/*-------------------------------------------------------------------------
|
||
*
|
||
* Created: H5Omessage.c
|
||
* Dec 3 2006
|
||
* Quincey Koziol <koziol@hdfgroup.org>
|
||
*
|
||
* Purpose: Object header message routines.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
|
||
/****************/
|
||
/* Module Setup */
|
||
/****************/
|
||
|
||
#include "H5Omodule.h" /* This source code file is part of the H5O module */
|
||
|
||
|
||
/***********/
|
||
/* Headers */
|
||
/***********/
|
||
#include "H5private.h" /* Generic Functions */
|
||
#include "H5Aprivate.h" /* Attributes */
|
||
#include "H5Eprivate.h" /* Error handling */
|
||
#include "H5Fprivate.h" /* File access */
|
||
#include "H5Iprivate.h" /* IDs */
|
||
#include "H5MMprivate.h" /* Memory management */
|
||
#include "H5Opkg.h" /* Object headers */
|
||
#include "H5SMprivate.h" /* Shared object header messages */
|
||
|
||
|
||
/****************/
|
||
/* Local Macros */
|
||
/****************/
|
||
|
||
|
||
/******************/
|
||
/* Local Typedefs */
|
||
/******************/
|
||
|
||
/* User data for iteration while removing a message */
|
||
typedef struct {
|
||
H5F_t *f; /* Pointer to file for insertion */
|
||
hid_t dxpl_id; /* DXPL during iteration */
|
||
int sequence; /* Sequence # to search for */
|
||
unsigned nfailed; /* # of failed message removals */
|
||
H5O_operator_t op; /* Callback routine for removal operations */
|
||
void *op_data; /* Callback data for removal operations */
|
||
hbool_t adj_link; /* Whether to adjust links when removing messages */
|
||
} H5O_iter_rm_t;
|
||
|
||
|
||
/********************/
|
||
/* Package Typedefs */
|
||
/********************/
|
||
|
||
|
||
/********************/
|
||
/* Local Prototypes */
|
||
/********************/
|
||
|
||
static herr_t H5O__msg_reset_real(const H5O_msg_class_t *type, void *native);
|
||
static herr_t H5O__msg_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
|
||
unsigned sequence, unsigned *oh_modified, void *_udata/*in,out*/);
|
||
static herr_t H5O__copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t idx,
|
||
const H5O_msg_class_t *type, const void *mesg, unsigned mesg_flags,
|
||
unsigned update_flags);
|
||
|
||
|
||
/*********************/
|
||
/* Package Variables */
|
||
/*********************/
|
||
|
||
|
||
/*****************************/
|
||
/* Library Private Variables */
|
||
/*****************************/
|
||
|
||
|
||
/*******************/
|
||
/* Local Variables */
|
||
/*******************/
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_create
|
||
*
|
||
* Purpose: Create a new object header message
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* Dec 1 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
|
||
unsigned update_flags, void *mesg, hid_t dxpl_id)
|
||
{
|
||
H5O_t *oh = NULL; /* Object header */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(loc);
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
|
||
HDassert(mesg);
|
||
|
||
/* Pin the object header */
|
||
if(NULL == (oh = H5O_pin(loc, dxpl_id)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
|
||
|
||
/* Go append message to object header */
|
||
if(H5O_msg_append_oh(loc->file, dxpl_id, oh, type_id, mesg_flags, update_flags, mesg) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to append to object header")
|
||
|
||
done:
|
||
if(oh && H5O_unpin(oh) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_create() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_append_oh
|
||
*
|
||
* Purpose: Simplified version of H5O_msg_create, used when creating a new
|
||
* object header message (usually during object creation) and
|
||
* several messages will be added to the object header at once.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Dec 31 2002
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_append_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
|
||
unsigned mesg_flags, unsigned update_flags, void *mesg)
|
||
{
|
||
const H5O_msg_class_t *type; /* Original H5O class type for the ID */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(H5O_ATTR_ID != type_id); /* Attributes are modified in another routine */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
|
||
HDassert(mesg);
|
||
|
||
/* Append new message to object header */
|
||
if(H5O_msg_append_real(f, dxpl_id, oh, type, mesg_flags, update_flags, mesg) < 0)
|
||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new message in header")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_append_oh() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_append_real
|
||
*
|
||
* Purpose: Append a new message to an object header.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* Dec 8 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_append_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
|
||
unsigned mesg_flags, unsigned update_flags, void *mesg)
|
||
{
|
||
size_t idx; /* Index of message to modify */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(type);
|
||
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
|
||
HDassert(mesg);
|
||
|
||
/* Allocate space for a new message */
|
||
if(H5O_msg_alloc(f, dxpl_id, oh, type, &mesg_flags, mesg, &idx) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "unable to create new message")
|
||
|
||
/* Copy the information for the message */
|
||
if(H5O__copy_mesg(f, dxpl_id, oh, idx, type, mesg, mesg_flags, update_flags) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to write message")
|
||
#ifdef H5O_DEBUG
|
||
H5O_assert(oh);
|
||
#endif /* H5O_DEBUG */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_append_real() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_write
|
||
*
|
||
* Purpose: Modifies an existing message or creates a new message.
|
||
*
|
||
* The UPDATE_FLAGS argument are flags that allow the caller
|
||
* to skip updating the modification time or reseting the message
|
||
* data. This is useful when several calls to H5O_msg_write will be
|
||
* made in a sequence.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* matzke@llnl.gov
|
||
* Aug 6 1997
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_write(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
|
||
unsigned update_flags, void *mesg, hid_t dxpl_id)
|
||
{
|
||
H5O_t *oh = NULL; /* Object header to use */
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(loc);
|
||
HDassert(loc->file);
|
||
HDassert(H5F_addr_defined(loc->addr));
|
||
HDassert(H5O_ATTR_ID != type_id); /* Attributes are modified in another routine */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(mesg);
|
||
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
|
||
|
||
/* Pin the object header */
|
||
if(NULL == (oh = H5O_pin(loc, dxpl_id)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
|
||
|
||
/* Call the "real" modify routine */
|
||
if(H5O_msg_write_real(loc->file, dxpl_id, oh, type, mesg_flags, update_flags, mesg) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message")
|
||
|
||
done:
|
||
if(oh && H5O_unpin(oh) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_write() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_write_oh
|
||
*
|
||
* Purpose: Modifies an existing message or creates a new message.
|
||
*
|
||
* The UPDATE_FLAGS argument are flags that allow the caller
|
||
* to skip updating the modification time or reseting the message
|
||
* data. This is useful when several calls to H5O_msg_write will be
|
||
* made in a sequence.
|
||
*
|
||
* Return: Success: Non-negative
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* Dec 6 2007
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_write_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
|
||
unsigned mesg_flags, unsigned update_flags, void *mesg)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_TAG(dxpl_id, oh->cache_info.addr, FAIL)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(H5O_ATTR_ID != type_id); /* Attributes are modified in another routine */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(mesg);
|
||
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
|
||
|
||
/* Call the "real" modify routine */
|
||
if(H5O_msg_write_real(f, dxpl_id, oh, type, mesg_flags, update_flags, mesg) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
|
||
} /* end H5O_msg_write_oh() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_write_real
|
||
*
|
||
* Purpose: Modifies an existing message or creates a new message.
|
||
*
|
||
* The UPDATE_FLAGS argument are flags that allow the caller
|
||
* to skip updating the modification time or reseting the message
|
||
* data. This is useful when several calls to H5O_msg_write will be
|
||
* made in a sequence.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* matzke@llnl.gov
|
||
* Aug 6 1997
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
|
||
unsigned mesg_flags, unsigned update_flags, void *mesg)
|
||
{
|
||
H5O_mesg_t *idx_msg; /* Pointer to message to modify */
|
||
size_t idx; /* Index of message to modify */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(type);
|
||
HDassert(type != H5O_MSG_ATTR);
|
||
HDassert(mesg);
|
||
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
|
||
|
||
/* Locate message of correct type */
|
||
for(idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++)
|
||
if(type == idx_msg->type)
|
||
break;
|
||
if(idx == oh->nmesgs)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message type not found")
|
||
|
||
/* Check for modifying a constant message */
|
||
if(!(update_flags & H5O_UPDATE_FORCE) && (idx_msg->flags & H5O_MSG_FLAG_CONSTANT))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify constant message")
|
||
/* This message is shared, but it's being modified. */
|
||
else if((idx_msg->flags & H5O_MSG_FLAG_SHARED) || (idx_msg->flags & H5O_MSG_FLAG_SHAREABLE)) {
|
||
htri_t status; /* Status of "try share" call */
|
||
|
||
/* First, sanity check to make sure it's not a committed message;
|
||
* these can't ever be modified.
|
||
*/
|
||
HDassert(((H5O_shared_t *)idx_msg->native)->type != H5O_SHARE_TYPE_COMMITTED);
|
||
|
||
/* Also, sanity check that a message doesn't switch status from being
|
||
* shared (or sharable) to being unsharable. (Which could cause
|
||
* a message to increase in size in the object header)
|
||
*/
|
||
HDassert(!(mesg_flags & H5O_MSG_FLAG_DONTSHARE));
|
||
|
||
/* Remove the old message from the SOHM index */
|
||
/* (It would be more efficient to try to share the message first, then
|
||
* delete it (avoiding thrashing the index in the case the ref.
|
||
* count on the message is one), but this causes problems when
|
||
* the location of the object changes (from in another object's
|
||
* header to the SOHM heap), so just delete it first -QAK)
|
||
*/
|
||
if(H5SM_delete(f, dxpl_id, oh, (H5O_shared_t *)idx_msg->native) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete message from SOHM index")
|
||
|
||
/* If we're replacing a shared message, the new message must be shared
|
||
* (or else it may increase in size!), so pass in NULL for the OH
|
||
* location.
|
||
*
|
||
* XXX: This doesn't handle freeing extra space in object header from
|
||
* a message shrinking.
|
||
*/
|
||
if((status = H5SM_try_share(f, dxpl_id, ((mesg_flags & H5O_MSG_FLAG_SHARED) ? NULL : oh), 0, idx_msg->type->id, mesg, &mesg_flags)) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "error while trying to share message")
|
||
if(status == FALSE && (mesg_flags & H5O_MSG_FLAG_SHARED))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "message changed sharing status")
|
||
} /* end if */
|
||
|
||
/* Copy the information for the message */
|
||
if(H5O__copy_mesg(f, dxpl_id, oh, idx, type, mesg, mesg_flags, update_flags) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to write message")
|
||
#ifdef H5O_DEBUG
|
||
H5O_assert(oh);
|
||
#endif /* H5O_DEBUG */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_write_real() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_read
|
||
*
|
||
* Purpose: Reads a message from an object header and returns a pointer
|
||
* to it. The caller will usually supply the memory through
|
||
* MESG and the return value will be MESG. But if MESG is
|
||
* the null pointer, then this function will malloc() memory
|
||
* to hold the result and return its pointer instead.
|
||
*
|
||
* Return: Success: Ptr to message in native format. The message
|
||
* should be freed by calling H5O_msg_reset(). If
|
||
* MESG is a null pointer then the caller should
|
||
* also call H5MM_xfree() on the return value
|
||
* after calling H5O_msg_reset().
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* matzke@llnl.gov
|
||
* Aug 6 1997
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void *
|
||
H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, void *mesg,
|
||
hid_t dxpl_id)
|
||
{
|
||
H5O_t *oh = NULL; /* Object header to use */
|
||
void *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_TAG(dxpl_id, loc->addr, NULL)
|
||
|
||
/* check args */
|
||
HDassert(loc);
|
||
HDassert(loc->file);
|
||
HDassert(H5F_addr_defined(loc->addr));
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
|
||
/* Get the object header */
|
||
if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header")
|
||
|
||
/* Call the "real" read routine */
|
||
if(NULL == (ret_value = H5O_msg_read_oh(loc->file, dxpl_id, oh, type_id, mesg)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header message")
|
||
|
||
done:
|
||
if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
|
||
|
||
FUNC_LEAVE_NOAPI_TAG(ret_value, NULL)
|
||
} /* end H5O_msg_read() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_read_oh
|
||
*
|
||
* Purpose: Reads a message from an object header and returns a pointer
|
||
* to it. The caller will usually supply the memory through
|
||
* MESG and the return value will be MESG. But if MESG is
|
||
* the null pointer, then this function will malloc() memory
|
||
* to hold the result and return its pointer instead.
|
||
*
|
||
* Return: Success: Ptr to message in native format. The message
|
||
* should be freed by calling H5O_msg_reset(). If
|
||
* MESG is a null pointer then the caller should
|
||
* also call H5MM_xfree() on the return value
|
||
* after calling H5O_msg_reset().
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* matzke@llnl.gov
|
||
* Aug 6 1997
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void *
|
||
H5O_msg_read_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
|
||
void *mesg)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
unsigned idx; /* Message's index in object header */
|
||
void *ret_value = NULL;
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* Scan through the messages looking for the right one */
|
||
for(idx = 0; idx < oh->nmesgs; idx++)
|
||
if(type == oh->mesg[idx].type)
|
||
break;
|
||
if(idx == oh->nmesgs)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, NULL, "message type not found")
|
||
|
||
/*
|
||
* Decode the message if necessary. If the message is shared then retrieve
|
||
* native message through the shared interface.
|
||
*/
|
||
H5O_LOAD_NATIVE(f, dxpl_id, 0, oh, &(oh->mesg[idx]), NULL)
|
||
|
||
/*
|
||
* The object header caches the native message (along with
|
||
* the raw message) so we must copy the native message before
|
||
* returning.
|
||
*/
|
||
if(NULL == (ret_value = (type->copy)(oh->mesg[idx].native, mesg)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy message to user space")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_read_oh() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_reset
|
||
*
|
||
* Purpose: Some message data structures have internal fields that
|
||
* need to be freed. This function does that if appropriate
|
||
* but doesn't free NATIVE.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* matzke@llnl.gov
|
||
* Aug 12 1997
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_reset(unsigned type_id, void *native)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* Call the "real" reset routine */
|
||
if(H5O__msg_reset_real(type, native) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTRESET, FAIL, "unable to reset object header")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_reset() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O__msg_reset_real
|
||
*
|
||
* Purpose: Some message data structures have internal fields that
|
||
* need to be freed. This function does that if appropriate
|
||
* but doesn't free NATIVE.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* matzke@llnl.gov
|
||
* Aug 12 1997
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5O__msg_reset_real(const H5O_msg_class_t *type, void *native)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_STATIC
|
||
|
||
/* check args */
|
||
HDassert(type);
|
||
|
||
if(native) {
|
||
if(type->reset) {
|
||
if((type->reset)(native) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "reset method failed")
|
||
} /* end if */
|
||
else
|
||
HDmemset(native, 0, type->native_size);
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O__msg_reset_real() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_free
|
||
*
|
||
* Purpose: Similar to H5O_msg_reset() except it also frees the message
|
||
* pointer.
|
||
*
|
||
* Return: Success: NULL
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Thursday, May 21, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void *
|
||
H5O_msg_free(unsigned type_id, void *mesg)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
void *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* check args */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* Call the "real" free routine */
|
||
ret_value = H5O_msg_free_real(type, mesg);
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_free() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_free_mesg
|
||
*
|
||
* Purpose: Call H5O_msg_free_real() on a message.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Tuesday, Sep 6, 2005
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_free_mesg(H5O_mesg_t *mesg)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* check args */
|
||
HDassert(mesg);
|
||
|
||
/* Free any native information */
|
||
mesg->native = H5O_msg_free_real(mesg->type, mesg->native);
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* end H5O_msg_free_mesg() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_free_real
|
||
*
|
||
* Purpose: Similar to H5O_msg_reset() except it also frees the message
|
||
* pointer.
|
||
*
|
||
* Return: Success: NULL
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Thursday, May 21, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void *
|
||
H5O_msg_free_real(const H5O_msg_class_t *type, void *msg_native)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* check args */
|
||
HDassert(type);
|
||
|
||
if(msg_native) {
|
||
H5O__msg_reset_real(type, msg_native);
|
||
if(NULL != (type->free))
|
||
(type->free)(msg_native);
|
||
else
|
||
H5MM_xfree(msg_native);
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(NULL)
|
||
} /* end H5O_msg_free_real() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_copy
|
||
*
|
||
* Purpose: Copies a message. If MESG is is the null pointer then a null
|
||
* pointer is returned with no error.
|
||
*
|
||
* Return: Success: Ptr to the new message
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Thursday, May 21, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void *
|
||
H5O_msg_copy(unsigned type_id, const void *mesg, void *dst)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
void *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(NULL)
|
||
|
||
/* check args */
|
||
HDassert(mesg);
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* Call the message class's copy routine */
|
||
if(NULL == (ret_value = (type->copy)(mesg, dst)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy object header message")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_copy() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_count
|
||
*
|
||
* Purpose: Counts the number of messages in an object header which are a
|
||
* certain type.
|
||
*
|
||
* Return: Success: Number of messages of specified type.
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Tuesday, April 21, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
int
|
||
H5O_msg_count(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
|
||
{
|
||
H5O_t *oh = NULL; /* Object header to operate on */
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
unsigned msg_count; /* Message count */
|
||
int ret_value = FAIL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* Check args */
|
||
HDassert(loc);
|
||
HDassert(loc->file);
|
||
HDassert(H5F_addr_defined(loc->addr));
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* Load 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")
|
||
|
||
/* Count the messages of the correct type */
|
||
msg_count = H5O_msg_count_real(oh, type);
|
||
H5_CHECKED_ASSIGN(ret_value, int, msg_count, unsigned);
|
||
|
||
done:
|
||
if(oh && H5O_unprotect(loc, 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)
|
||
} /* end H5O_msg_count() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_count_real
|
||
*
|
||
* Purpose: Counts the number of messages in an object header which are a
|
||
* certain type.
|
||
*
|
||
* Return: Success: Number of messages of specified type.
|
||
*
|
||
* Failure: (can't fail)
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Tuesday, February 6, 2007
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
unsigned
|
||
H5O_msg_count_real(const H5O_t *oh, const H5O_msg_class_t *type)
|
||
{
|
||
unsigned u; /* Local index variable */
|
||
unsigned ret_value = 0; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check args */
|
||
HDassert(oh);
|
||
HDassert(type);
|
||
|
||
/* Loop over all messages, counting the ones of the type looked for */
|
||
for(u = ret_value = 0; u < oh->nmesgs; u++)
|
||
if(oh->mesg[u].type == type)
|
||
ret_value++;
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_count_real() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_exists
|
||
*
|
||
* Purpose: Determines if a particular message exists in an object
|
||
* header without trying to decode the message.
|
||
*
|
||
* Return: Success: FALSE if the message does not exist; TRUE if
|
||
* th message exists.
|
||
*
|
||
* Failure: FAIL if the existence of the message could
|
||
* not be determined due to some error such as
|
||
* not being able to read the object header.
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Monday, November 2, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
htri_t
|
||
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 = FAIL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_TAG(dxpl_id, loc->addr, FAIL)
|
||
|
||
HDassert(loc);
|
||
HDassert(loc->file);
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
|
||
/* Load 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")
|
||
|
||
/* Call the "real" exists routine */
|
||
if((ret_value = H5O_msg_exists_oh(oh, type_id)) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_READERROR, FAIL, "unable to verify object header message")
|
||
|
||
done:
|
||
if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
|
||
|
||
FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
|
||
} /* end H5O_msg_exists() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_exists_oh
|
||
*
|
||
* Purpose: Determines if a particular message exists in an object
|
||
* header without trying to decode the message.
|
||
*
|
||
* Return: Success: FALSE if the message does not exist; TRUE if
|
||
* th message exists.
|
||
*
|
||
* Failure: FAIL if the existence of the message could
|
||
* not be determined due to some error such as
|
||
* not being able to read the object header.
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* Monday, November 2, 1998
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
htri_t
|
||
H5O_msg_exists_oh(const H5O_t *oh, unsigned type_id)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
unsigned u; /* Local index variable */
|
||
htri_t ret_value = FALSE; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
HDassert(oh);
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* Scan through the messages looking for the right one */
|
||
for(u = 0; u < oh->nmesgs; u++)
|
||
if(type == oh->mesg[u].type)
|
||
HGOTO_DONE(TRUE)
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_exists_oh() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_remove
|
||
*
|
||
* Purpose: Removes the specified message from the object header.
|
||
* If sequence is H5O_ALL (-1) then all messages of the
|
||
* specified type are removed. Removing a message causes
|
||
* the sequence numbers to change for subsequent messages of
|
||
* the same type.
|
||
*
|
||
* No attempt is made to join adjacent free areas of the
|
||
* object header into a single larger free area.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* matzke@llnl.gov
|
||
* Aug 28 1997
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_remove(const H5O_loc_t *loc, unsigned type_id, int sequence, hbool_t adj_link,
|
||
hid_t dxpl_id)
|
||
{
|
||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
herr_t ret_value = FAIL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(loc);
|
||
HDassert(loc->file);
|
||
HDassert(H5F_addr_defined(loc->addr));
|
||
HDassert(H5O_ATTR_ID != type_id); /* Attributes are modified in another routine */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* Pin the object header */
|
||
if(NULL == (oh = H5O_pin(loc, dxpl_id)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
|
||
|
||
/* Call the "real" remove routine */
|
||
if((ret_value = H5O_msg_remove_real(loc->file, oh, type, sequence, NULL, NULL, adj_link, dxpl_id)) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to remove object header message")
|
||
|
||
done:
|
||
if(oh && H5O_unpin(oh) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_remove() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_remove_op
|
||
*
|
||
* Purpose: Removes messages from the object header that a callback
|
||
* routine indicates should be removed.
|
||
*
|
||
* No attempt is made to join adjacent free areas of the
|
||
* object header into a single larger free area.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Sep 6 2005
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_remove_op(const H5O_loc_t *loc, unsigned type_id, int sequence,
|
||
H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id)
|
||
{
|
||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
herr_t ret_value = FAIL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(loc);
|
||
HDassert(loc->file);
|
||
HDassert(H5F_addr_defined(loc->addr));
|
||
HDassert(H5O_ATTR_ID != type_id); /* Attributes are modified in another routine */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* Pin the object header */
|
||
if(NULL == (oh = H5O_pin(loc, dxpl_id)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
|
||
|
||
/* Call the "real" remove routine */
|
||
if((ret_value = H5O_msg_remove_real(loc->file, oh, type, sequence, op, op_data, adj_link, dxpl_id)) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to remove object header message")
|
||
|
||
done:
|
||
if(oh && H5O_unpin(oh) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_remove_op() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O__msg_remove_cb
|
||
*
|
||
* Purpose: Object header iterator callback routine to remove messages
|
||
* of a particular type that match a particular sequence number,
|
||
* or all messages if the sequence number is H5O_ALL (-1).
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Sep 6 2005
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5O__msg_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned sequence,
|
||
unsigned *oh_modified, void *_udata/*in,out*/)
|
||
{
|
||
H5O_iter_rm_t *udata = (H5O_iter_rm_t *)_udata; /* Operator user data */
|
||
htri_t try_remove = FALSE; /* Whether to try removing a message */
|
||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||
|
||
FUNC_ENTER_STATIC
|
||
|
||
/* check args */
|
||
HDassert(mesg);
|
||
|
||
/* Check for callback routine */
|
||
if(udata->op) {
|
||
/* Call the iterator callback */
|
||
if((try_remove = (udata->op)(mesg->native, sequence, udata->op_data)) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "object header message deletion callback failed")
|
||
} /* end if */
|
||
else {
|
||
/* If there's no callback routine, does the sequence # match? */
|
||
if((int)sequence == udata->sequence || H5O_ALL == udata->sequence)
|
||
try_remove = TRUE;
|
||
} /* end else */
|
||
|
||
/* Try removing the message, if indicated */
|
||
if(try_remove) {
|
||
/*
|
||
* Keep track of how many times we failed trying to remove constant
|
||
* messages.
|
||
* (OK to remove constant messages - QAK)
|
||
*/
|
||
/* Convert message into a null message */
|
||
if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, udata->adj_link) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to release message")
|
||
|
||
/* Indicate that the object header was modified */
|
||
*oh_modified = H5O_MODIFY_CONDENSE;
|
||
|
||
/* Break out now, if we've found the correct message */
|
||
if(udata->sequence == H5O_FIRST || udata->sequence != H5O_ALL)
|
||
HGOTO_DONE(H5_ITER_STOP)
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O__msg_remove_cb() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_remove_real
|
||
*
|
||
* Purpose: Removes the specified message from the object header.
|
||
* If sequence is H5O_ALL (-1) then all messages of the
|
||
* specified type are removed. Removing a message causes
|
||
* the sequence numbers to change for subsequent messages of
|
||
* the same type.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Robb Matzke
|
||
* matzke@llnl.gov
|
||
* Aug 28 1997
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_remove_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
|
||
int sequence, H5O_operator_t app_op, void *op_data, hbool_t adj_link,
|
||
hid_t dxpl_id)
|
||
{
|
||
H5O_iter_rm_t udata; /* User data for iterator */
|
||
H5O_mesg_operator_t op; /* Wrapper for operator */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(type);
|
||
|
||
/* Make certain we are allowed to modify the file */
|
||
if(0 == (H5F_INTENT(f) & H5F_ACC_RDWR))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file")
|
||
|
||
/* Set up iterator operator data */
|
||
udata.f = f;
|
||
udata.dxpl_id = dxpl_id;
|
||
udata.sequence = sequence;
|
||
udata.nfailed = 0;
|
||
udata.op = app_op;
|
||
udata.op_data = op_data;
|
||
udata.adj_link = adj_link;
|
||
|
||
/* Iterate over the messages, deleting appropriate one(s) */
|
||
op.op_type = H5O_MESG_OP_LIB;
|
||
op.u.lib_op = H5O__msg_remove_cb;
|
||
if(H5O_msg_iterate_real(f, oh, type, &op, &udata, dxpl_id) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "error iterating over messages")
|
||
|
||
/* Fail if we tried to remove any constant messages */
|
||
if(udata.nfailed)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to remove constant message(s)")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_remove_real() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_iterate
|
||
*
|
||
* Purpose: Iterate through object headers of a certain type.
|
||
*
|
||
* Return: Returns a negative value if something is wrong, the return
|
||
* value of the last operator if it was non-zero, or zero if all
|
||
* object headers were processed.
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Nov 19 2004
|
||
*
|
||
* Description:
|
||
* This function interates over the object headers of an object
|
||
* specified with 'loc' of type 'type_id'. For each object header of the
|
||
* object, the 'op_data' and some additional information (specified below) are
|
||
* passed to the 'op' function.
|
||
* The operation receives a pointer to the object header message for the
|
||
* object being iterated over ('mesg'), and the pointer to the operator data
|
||
* passed in to H5O_msg_iterate ('op_data'). The return values from an operator
|
||
* are:
|
||
* A. Zero causes the iterator to continue, returning zero when all
|
||
* object headers of that type have been processed.
|
||
* B. Positive causes the iterator to immediately return that positive
|
||
* value, indicating short-circuit success.
|
||
* C. Negative causes the iterator to immediately return that value,
|
||
* indicating failure.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_iterate(const H5O_loc_t *loc, unsigned type_id,
|
||
const H5O_mesg_operator_t *op, void *op_data, hid_t dxpl_id)
|
||
{
|
||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
herr_t ret_value = FAIL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(loc);
|
||
HDassert(loc->file);
|
||
HDassert(H5F_addr_defined(loc->addr));
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(op);
|
||
|
||
/* Protect the object header to iterate over */
|
||
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")
|
||
|
||
/* Call the "real" iterate routine */
|
||
if((ret_value = H5O_msg_iterate_real(loc->file, oh, type, op, op_data, dxpl_id)) < 0)
|
||
HERROR(H5E_OHDR, H5E_BADITER, "unable to iterate over object header messages");
|
||
|
||
done:
|
||
if(oh && H5O_unprotect(loc, 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)
|
||
} /* end H5O_msg_iterate() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_iterate_real
|
||
*
|
||
* Purpose: Iterate through object headers of a certain type.
|
||
*
|
||
* Return: Returns a negative value if something is wrong, the return
|
||
* value of the last operator if it was non-zero, or zero if all
|
||
* object headers were processed.
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Sep 6 2005
|
||
*
|
||
* Description:
|
||
* This function interates over the object headers of an object
|
||
* specified with 'ent' of type 'type_id'. For each object header of the
|
||
* object, the 'op_data' and some additional information (specified below) are
|
||
* passed to the 'op' function.
|
||
* The operation receives a pointer to the object header message for the
|
||
* object being iterated over ('mesg'), and the pointer to the operator data
|
||
* passed in to H5O_msg_iterate ('op_data'). The return values from an operator
|
||
* are:
|
||
* A. Zero causes the iterator to continue, returning zero when all
|
||
* object headers of that type have been processed.
|
||
* B. Positive causes the iterator to immediately return that positive
|
||
* value, indicating short-circuit success.
|
||
* C. Negative causes the iterator to immediately return that value,
|
||
* indicating failure.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
|
||
const H5O_mesg_operator_t *op, void *op_data, hid_t dxpl_id)
|
||
{
|
||
H5O_mesg_t *idx_msg; /* Pointer to current message */
|
||
unsigned idx; /* Absolute index of current message in all messages */
|
||
unsigned sequence; /* Relative index of current message for messages of type */
|
||
unsigned oh_modified = 0; /* Whether the callback modified the object header */
|
||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(type);
|
||
HDassert(op);
|
||
HDassert(op->u.app_op);
|
||
|
||
/* Iterate over messages */
|
||
for(sequence = 0, idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs && !ret_value; idx++, idx_msg++) {
|
||
if(type == idx_msg->type) {
|
||
/* Decode the message if necessary. */
|
||
H5O_LOAD_NATIVE(f, dxpl_id, 0, oh, idx_msg, FAIL)
|
||
|
||
/* Check for making an "internal" (i.e. within the H5O package) callback */
|
||
if(op->op_type == H5O_MESG_OP_LIB)
|
||
ret_value = (op->u.lib_op)(oh, idx_msg, sequence, &oh_modified, op_data);
|
||
else
|
||
ret_value = (op->u.app_op)(idx_msg->native, sequence, op_data);
|
||
|
||
/* Check for iterator callback indicating to get out of loop */
|
||
if(ret_value != 0)
|
||
break;
|
||
|
||
/* Increment sequence value for message type */
|
||
sequence++;
|
||
} /* end if */
|
||
} /* end for */
|
||
|
||
/* Check for error from iterator */
|
||
if(ret_value < 0)
|
||
HERROR(H5E_OHDR, H5E_CANTLIST, "iterator function failed");
|
||
|
||
done:
|
||
/* Check if object message was modified */
|
||
if(oh_modified) {
|
||
/* Try to condense object header info */
|
||
/* (Since this routine is used to remove messages from an
|
||
* object header, the header will be condensed after each
|
||
* message removal)
|
||
*/
|
||
if(oh_modified & H5O_MODIFY_CONDENSE)
|
||
if(H5O_condense_header(f, oh, dxpl_id) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't pack object header")
|
||
|
||
/* Mark object header as changed */
|
||
if(H5O_touch_oh(f, dxpl_id, oh, FALSE) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
|
||
|
||
/* Mark object header as dirty in cache */
|
||
if(H5AC_mark_entry_dirty(oh) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_iterate_real() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_raw_size
|
||
*
|
||
* Purpose: Call the 'raw_size' method for a
|
||
* particular class of object header.
|
||
*
|
||
* Return: Size of message on success, 0 on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Feb 13 2003
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
size_t
|
||
H5O_msg_raw_size(const H5F_t *f, unsigned type_id, hbool_t disable_shared,
|
||
const void *mesg)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
size_t ret_value = 0; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(0)
|
||
|
||
/* Check args */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(type->raw_size);
|
||
HDassert(f);
|
||
HDassert(mesg);
|
||
|
||
/* Compute the raw data size for the mesg */
|
||
if(0 == (ret_value = (type->raw_size)(f, disable_shared, mesg)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_raw_size() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_size_f
|
||
*
|
||
* Purpose: Calculate the final size of an encoded message in an object
|
||
* header.
|
||
*
|
||
* Note: This routine assumes that the message size will be used in the
|
||
* creation of a new object header.
|
||
*
|
||
* Return: Size of message on success, 0 on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Sep 6 2005
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
size_t
|
||
H5O_msg_size_f(const H5F_t *f, hid_t ocpl_id, unsigned type_id,
|
||
const void *mesg, size_t extra_raw)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
H5P_genplist_t *ocpl; /* Object Creation Property list */
|
||
uint8_t oh_flags; /* Object header status flags */
|
||
size_t ret_value = 0; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(0)
|
||
|
||
/* Check args */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(type->raw_size);
|
||
HDassert(f);
|
||
HDassert(mesg);
|
||
|
||
/* Get the property list */
|
||
if(NULL == (ocpl = (H5P_genplist_t *)H5I_object(ocpl_id)))
|
||
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, 0, "not a property list")
|
||
|
||
/* Get any object header status flags set by properties */
|
||
if(H5P_get(ocpl, H5O_CRT_OHDR_FLAGS_NAME, &oh_flags) < 0)
|
||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, 0, "can't get object header flags")
|
||
|
||
|
||
/* Compute the raw data size for the mesg */
|
||
if((ret_value = (type->raw_size)(f, FALSE, mesg)) == 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message")
|
||
|
||
/* Add in "extra" raw space */
|
||
ret_value += extra_raw;
|
||
|
||
/* Adjust size for alignment, if necessary */
|
||
ret_value = (size_t)H5O_ALIGN_F(f, ret_value);
|
||
|
||
/* Add space for message header */
|
||
ret_value += (size_t)H5O_SIZEOF_MSGHDR_F(f,
|
||
(H5F_STORE_MSG_CRT_IDX(f) || oh_flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED));
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_size_f() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_size_oh
|
||
*
|
||
* Purpose: Calculate the final size of an encoded message in an object
|
||
* header.
|
||
*
|
||
* Note: This routine assumes that the message is already used in
|
||
* an object header.
|
||
*
|
||
* Return: Size of message on success, 0 on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* Mar 7 2007
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
size_t
|
||
H5O_msg_size_oh(const H5F_t *f, const H5O_t *oh, unsigned type_id,
|
||
const void *mesg, size_t extra_raw)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
size_t ret_value = 0; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(0)
|
||
|
||
/* Check args */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(type->raw_size);
|
||
HDassert(f);
|
||
HDassert(mesg);
|
||
|
||
/* Compute the raw data size for the mesg */
|
||
if((ret_value = (type->raw_size)(f, FALSE, mesg)) == 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message")
|
||
|
||
/* Add in "extra" raw space */
|
||
ret_value += extra_raw;
|
||
|
||
/* Adjust size for alignment, if necessary */
|
||
ret_value = (size_t)H5O_ALIGN_OH(oh, ret_value);
|
||
|
||
/* Add space for message header */
|
||
ret_value += (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_size_oh() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_can_share
|
||
*
|
||
* Purpose: Call the 'can share' method for a
|
||
* particular class of object header. This returns TRUE
|
||
* if the message is allowed to be put in the shared message
|
||
* heap and false otherwise (e.g., for committed or immutable
|
||
* datatypes).
|
||
*
|
||
* Return: Object can be shared: TRUE
|
||
* Object cannot be shared: FALSE
|
||
*
|
||
* Programmer: James Laird
|
||
* January 12 2007
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
htri_t
|
||
H5O_msg_can_share(unsigned type_id, const void *mesg)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
htri_t ret_value = FAIL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check args */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(mesg);
|
||
|
||
/* If there is a can_share callback, use it */
|
||
if(type->can_share)
|
||
ret_value = (type->can_share)(mesg);
|
||
else {
|
||
/* Otherwise, the message can be shared if messages of this type are
|
||
* shareable in general; i.e., if they have the "is_sharable" flag
|
||
* in the "share_flags" class member set.
|
||
*/
|
||
ret_value = (type->share_flags & H5O_SHARE_IS_SHARABLE) ? TRUE : FALSE;
|
||
} /* end else */
|
||
|
||
/* If the message is shareable, both copy_file and post_copy_file must be
|
||
* defined */
|
||
HDassert((type->post_copy_file && type->copy_file) || ret_value == FALSE);
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_can_share() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_can_share_in_ohdr
|
||
*
|
||
* Purpose: Check if the message class allows its messages to be shared
|
||
* in the object's header.
|
||
*
|
||
* Return: Object can be shared: TRUE
|
||
* Object cannot be shared: FALSE
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* March 15 2007
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
htri_t
|
||
H5O_msg_can_share_in_ohdr(unsigned type_id)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
htri_t ret_value = FAIL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check args */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* Otherwise, the message can be shared if messages of this type are
|
||
* shareable in general; i.e., if they have the "is_sharable" flag
|
||
* in the "share_flags" class member set.
|
||
*/
|
||
ret_value = (type->share_flags & H5O_SHARE_IN_OHDR) ? TRUE : FALSE;
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_can_share_in_ohdr() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_is_shared
|
||
*
|
||
* Purpose: Call the 'is_shared' method for a
|
||
* particular class of object header.
|
||
*
|
||
* Return: Object is shared: TRUE
|
||
* Object is not shared: FALSE
|
||
*
|
||
* Programmer: James Laird
|
||
* jlaird@ncsa.uiuc.edu
|
||
* April 5 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
htri_t
|
||
H5O_msg_is_shared(unsigned type_id, const void *mesg)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
htri_t ret_value = FAIL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check args */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(mesg);
|
||
|
||
/* If messages in a class aren't sharable, then obviously this message isn't shared! :-) */
|
||
if(type->share_flags & H5O_SHARE_IS_SHARABLE)
|
||
ret_value = H5O_IS_STORED_SHARED(((const H5O_shared_t *)mesg)->type);
|
||
else
|
||
ret_value = FALSE;
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_is_shared() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_set_share
|
||
*
|
||
* Purpose: Set the shared information for an object header message.
|
||
*
|
||
* Return: Success: Non-negative
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: James Laird
|
||
* jlaird@hdfgroup.org
|
||
* November 1 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_set_share(unsigned type_id, const H5O_shared_t *share, void *mesg)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* Check args */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE);
|
||
HDassert(mesg);
|
||
HDassert(share);
|
||
HDassert(share->type != H5O_SHARE_TYPE_UNSHARED);
|
||
|
||
/* If there's a special action for this class that needs to be performed
|
||
* when setting the shared component, do that
|
||
*/
|
||
if(type->set_share) {
|
||
if((type->set_share)(mesg, share) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information")
|
||
} /* end if */
|
||
else {
|
||
/* Set this message as the shared component for the message, wiping out
|
||
* any information that was there before
|
||
*/
|
||
if(H5O_set_shared((H5O_shared_t *)mesg, share) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information")
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_set_share() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_reset_share
|
||
*
|
||
* Purpose: Reset the shared information for an object header message.
|
||
*
|
||
* Return: Success: Non-negative
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: James Laird
|
||
* jlaird@hdfgroup.org
|
||
* Oct 17 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_reset_share(unsigned type_id, void *mesg)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check args */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE);
|
||
HDassert(mesg);
|
||
|
||
/* Reset the shared component in the message to zero. */
|
||
HDmemset((H5O_shared_t *)mesg, 0, sizeof(H5O_shared_t));
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* end H5O_msg_reset_share() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_get_crt_index
|
||
*
|
||
* Purpose: Call the 'get creation index' method for a message.
|
||
*
|
||
* Return: Success: Non-negative
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* March 15 2007
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_get_crt_index(unsigned type_id, const void *mesg, H5O_msg_crt_idx_t *crt_idx)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
herr_t ret_value = SUCCEED;
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* Check args */
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
HDassert(mesg);
|
||
HDassert(crt_idx);
|
||
|
||
/* If there is a "get_crt_index callback, use it */
|
||
if(type->get_crt_index) {
|
||
/* Retrieve the creation index from the native message */
|
||
if((type->get_crt_index)(mesg, crt_idx) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve creation index")
|
||
} /* end if */
|
||
else
|
||
*crt_idx = 0;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_get_crt_index() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_encode
|
||
*
|
||
* Purpose: Encode an object(data type and simple data space only)
|
||
* description into a buffer.
|
||
*
|
||
* Return: Success: Non-negative
|
||
*
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Raymond Lu
|
||
* slu@ncsa.uiuc.edu
|
||
* July 13, 2004
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_encode(H5F_t *f, unsigned type_id, hbool_t disable_shared,
|
||
unsigned char *buf, const void *mesg)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* Encode */
|
||
if((type->encode)(f, disable_shared, buf, mesg) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode message")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_encode() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_decode
|
||
*
|
||
* Purpose: Decode a binary object description and return a new
|
||
* object handle.
|
||
*
|
||
* Return: Success: Pointer to object(data type or space)
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Raymond Lu
|
||
* slu@ncsa.uiuc.edu
|
||
* July 14, 2004
|
||
*
|
||
* Modifications: Neil Fortner
|
||
* Feb 4 2009
|
||
* Added open_oh parameter. This parameter is optional and
|
||
* contains this message's protected object header
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void *
|
||
H5O_msg_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id,
|
||
const unsigned char *buf)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
unsigned ioflags = 0; /* Flags for decode routine */
|
||
void *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(NULL)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* decode */
|
||
if((ret_value = (type->decode)(f, dxpl_id, open_oh, 0, &ioflags, buf)) == NULL)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode message")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_decode() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_copy_file
|
||
*
|
||
* Purpose: Copies a message to file. If MESG is is the null pointer then a null
|
||
* pointer is returned with no error.
|
||
*
|
||
* Attempts to share the message in the destination and sets
|
||
* SHARED to TRUE or FALSE depending on whether this succeeds.
|
||
*
|
||
* Return: Success: Ptr to the new message
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Peter Cao
|
||
* June 4, 2005
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
void *
|
||
H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src,
|
||
void *native_src, H5F_t *file_dst, hbool_t *recompute_size,
|
||
unsigned *mesg_flags, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id)
|
||
{
|
||
void *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* check args */
|
||
HDassert(type);
|
||
HDassert(type->copy_file);
|
||
HDassert(file_src);
|
||
HDassert(native_src);
|
||
HDassert(file_dst);
|
||
HDassert(recompute_size);
|
||
HDassert(cpy_info);
|
||
|
||
/* The copy_file callback will return an H5O_shared_t only if the message
|
||
* to be copied is a committed datatype.
|
||
*/
|
||
if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, recompute_size, mesg_flags, cpy_info, udata, dxpl_id)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object header message to file")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_copy_file() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_alloc
|
||
*
|
||
* Purpose: Create a new message in an object header
|
||
*
|
||
* Return: Success: Index of message
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Friday, September 3, 2003
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
|
||
unsigned *mesg_flags, void *native, size_t *mesg_idx)
|
||
{
|
||
size_t new_idx; /* New index for message */
|
||
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(mesg_flags);
|
||
HDassert(!(*mesg_flags & H5O_MSG_FLAG_SHARED));
|
||
HDassert(type);
|
||
HDassert(native);
|
||
HDassert(mesg_idx);
|
||
|
||
/* Check if message is already shared */
|
||
if((shared_mesg = H5O_msg_is_shared(type->id, native)) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "error determining if message is shared")
|
||
else if(shared_mesg > 0) {
|
||
/* Increment message's reference count */
|
||
if(type->link && (type->link)(f, dxpl_id, oh, native) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared message ref count")
|
||
*mesg_flags |= H5O_MSG_FLAG_SHARED;
|
||
} /* end if */
|
||
else {
|
||
/* Attempt to share message */
|
||
if(H5SM_try_share(f, dxpl_id, oh, 0, type->id, native, mesg_flags) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "error determining if message should be shared")
|
||
} /* end else */
|
||
|
||
/* Allocate space in the object header for the message */
|
||
if(H5O_alloc(f, dxpl_id, oh, type, native, &new_idx) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for message")
|
||
|
||
/* Get the message's "creation index", if it has one */
|
||
if(type->get_crt_index) {
|
||
/* Retrieve the creation index from the native message */
|
||
if((type->get_crt_index)(native, &oh->mesg[new_idx].crt_idx) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve creation index")
|
||
} /* end if */
|
||
|
||
/* Set new message index */
|
||
*mesg_idx = new_idx;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_alloc() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O__copy_mesg
|
||
*
|
||
* Purpose: Make a copy of the native object for an object header's
|
||
* native message info
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Friday, September 3, 2003
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5O__copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t idx,
|
||
const H5O_msg_class_t *type, const void *mesg, unsigned mesg_flags,
|
||
unsigned update_flags)
|
||
{
|
||
H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */
|
||
H5O_mesg_t *idx_msg = &oh->mesg[idx]; /* Pointer to message to modify */
|
||
hbool_t chk_dirtied = FALSE; /* Flag for unprotecting chunk */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_STATIC
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
HDassert(type);
|
||
HDassert(type->copy);
|
||
HDassert(mesg);
|
||
|
||
/* Protect chunk */
|
||
if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, idx_msg->chunkno)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header chunk")
|
||
|
||
/* Reset existing native information for the header's message */
|
||
H5O__msg_reset_real(type, idx_msg->native);
|
||
|
||
/* Copy the native object for the message */
|
||
if(NULL == (idx_msg->native = (type->copy)(mesg, idx_msg->native)))
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy message to object header")
|
||
|
||
/* Update the message flags */
|
||
idx_msg->flags = (uint8_t)mesg_flags;
|
||
|
||
/* Mark the message as modified */
|
||
idx_msg->dirty = TRUE;
|
||
chk_dirtied = TRUE;
|
||
|
||
/* Release chunk */
|
||
if(H5O_chunk_unprotect(f, dxpl_id, chk_proxy, chk_dirtied) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
|
||
chk_proxy = NULL;
|
||
|
||
/* Update the modification time, if requested */
|
||
if(update_flags & H5O_UPDATE_TIME)
|
||
if(H5O_touch_oh(f, dxpl_id, oh, FALSE) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
|
||
|
||
done:
|
||
/* Release chunk, if not already released */
|
||
if(chk_proxy && H5O_chunk_unprotect(f, dxpl_id, chk_proxy, chk_dirtied) < 0)
|
||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O__copy_mesg() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_delete
|
||
*
|
||
* Purpose: Calls a message's delete callback.
|
||
*
|
||
* This is mostly redundant with H5O_delete_mesg below,
|
||
* but H5O_delete_mesg only works on messages in object headers
|
||
* (while the shared message code needs to delete messages in
|
||
* the heap).
|
||
*
|
||
* open_oh is a pointer to a currently open object header so
|
||
* that the library doesn't try to re-protect it. If there is
|
||
* no such object header, it should be NULL.
|
||
*
|
||
* Return: Success: Non-negative
|
||
* Failure: Negative
|
||
*
|
||
* Programmer: James Laird
|
||
* December 21, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id,
|
||
void *mesg)
|
||
{
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* delete */
|
||
if((type->del) && (type->del)(f, dxpl_id, open_oh, mesg) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_delete() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_delete_mesg
|
||
*
|
||
* Purpose: Internal function to:
|
||
* Delete an object header message from a file. This frees the file
|
||
* space used for anything referred to in the object header message.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* September 26 2003
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_mesg_t *mesg)
|
||
{
|
||
const H5O_msg_class_t *type = mesg->type; /* Type of object to free */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* Check args */
|
||
HDassert(f);
|
||
HDassert(mesg);
|
||
HDassert(oh);
|
||
|
||
/* Check if there is a file space deletion callback for this type of message */
|
||
if(type->del) {
|
||
/* Decode the message if necessary. */
|
||
H5O_LOAD_NATIVE(f, dxpl_id, H5O_DECODEIO_NOCHANGE, oh, mesg, FAIL)
|
||
|
||
if((type->del)(f, dxpl_id, oh, mesg->native) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_delete_mesg() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_flush
|
||
*
|
||
* Purpose: Flushes a message for an object header.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* May 14 2007
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_flush(H5F_t *f, H5O_t *oh, H5O_mesg_t *mesg)
|
||
{
|
||
uint8_t *p; /* Temporary pointer to encode with */
|
||
unsigned msg_id; /* ID for message */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
|
||
/* Point into message's chunk's image */
|
||
p = mesg->raw - H5O_SIZEOF_MSGHDR_OH(oh);
|
||
|
||
/* Retrieve actual message ID, for unknown messages */
|
||
if(mesg->type == H5O_MSG_UNKNOWN)
|
||
msg_id = *(H5O_unknown_t *)(mesg->native);
|
||
else
|
||
msg_id = (uint8_t)mesg->type->id;
|
||
|
||
/* Encode the message prefix */
|
||
if(oh->version == H5O_VERSION_1)
|
||
UINT16ENCODE(p, msg_id)
|
||
else
|
||
*p++ = (uint8_t)msg_id;
|
||
HDassert(mesg->raw_size < H5O_MESG_MAX_SIZE);
|
||
UINT16ENCODE(p, mesg->raw_size);
|
||
*p++ = mesg->flags;
|
||
|
||
/* Only encode reserved bytes for version 1 of format */
|
||
if(oh->version == H5O_VERSION_1) {
|
||
*p++ = 0; /*reserved*/
|
||
*p++ = 0; /*reserved*/
|
||
*p++ = 0; /*reserved*/
|
||
} /* end for */
|
||
/* Only encode creation index for version 2+ of format */
|
||
else {
|
||
/* Only encode creation index if they are being tracked */
|
||
if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
|
||
UINT16ENCODE(p, mesg->crt_idx);
|
||
} /* end else */
|
||
HDassert(p == mesg->raw);
|
||
|
||
#ifndef NDEBUG
|
||
/* Make certain that null messages aren't in chunks w/gaps */
|
||
if(H5O_NULL_ID == msg_id)
|
||
HDassert(oh->chunk[mesg->chunkno].gap == 0);
|
||
else
|
||
/* Non-null messages should always have a native pointer */
|
||
HDassert(mesg->native);
|
||
#endif /* NDEBUG */
|
||
|
||
/* Encode the message itself, if it's not an "unknown" message */
|
||
if(mesg->native && mesg->type != H5O_MSG_UNKNOWN) {
|
||
/*
|
||
* Encode the message. If the message is shared then we
|
||
* encode a Shared Object message instead of the object
|
||
* which is being shared.
|
||
*/
|
||
HDassert(mesg->raw >= oh->chunk[mesg->chunkno].image);
|
||
HDassert(mesg->raw_size == H5O_ALIGN_OH(oh, mesg->raw_size));
|
||
HDassert(mesg->raw + mesg->raw_size <=
|
||
oh->chunk[mesg->chunkno].image + (oh->chunk[mesg->chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh)));
|
||
#ifndef NDEBUG
|
||
/* Sanity check that the message won't overwrite past it's allocated space */
|
||
{
|
||
size_t msg_size;
|
||
|
||
msg_size = mesg->type->raw_size(f, FALSE, mesg->native);
|
||
msg_size = H5O_ALIGN_OH(oh, msg_size);
|
||
HDassert(msg_size <= mesg->raw_size);
|
||
}
|
||
#endif /* NDEBUG */
|
||
HDassert(mesg->type->encode);
|
||
if((mesg->type->encode)(f, FALSE, mesg->raw, mesg->native) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message")
|
||
} /* end if */
|
||
|
||
/* Mark the message as clean now */
|
||
mesg->dirty = FALSE;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_msg_flush() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_flush_msgs
|
||
*
|
||
* Purpose: Flushes messages for object header.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* Nov 21 2005
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_flush_msgs(H5F_t *f, H5O_t *oh)
|
||
{
|
||
H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */
|
||
unsigned u; /* Local index variable */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(f);
|
||
HDassert(oh);
|
||
|
||
/* Encode any dirty messages */
|
||
for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++)
|
||
if(curr_msg->dirty)
|
||
if(H5O_msg_flush(f, oh, curr_msg) < 0)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message")
|
||
|
||
/* Sanity check for the correct # of messages in object header */
|
||
if(oh->nmesgs != u)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "corrupt object header - too few messages")
|
||
|
||
#ifndef NDEBUG
|
||
/* Reset the number of messages dirtied by decoding, as they have all
|
||
* been flushed */
|
||
oh->ndecode_dirtied = 0;
|
||
#endif /* NDEBUG */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5O_flush_msgs() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5O_msg_get_flags
|
||
*
|
||
* Purpose: Queries a message's message flags in the object header
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Vailin; Jan 2013
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5O_msg_get_flags(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id, uint8_t *flags)
|
||
{
|
||
H5O_t *oh = NULL; /* Object header to use */
|
||
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
|
||
H5O_mesg_t *idx_msg; /* Pointer to message to modify */
|
||
unsigned idx; /* Index of message to modify */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(FAIL)
|
||
|
||
/* check args */
|
||
HDassert(loc);
|
||
HDassert(loc->file);
|
||
HDassert(H5F_addr_defined(loc->addr));
|
||
HDassert(type_id < NELMTS(H5O_msg_class_g));
|
||
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
|
||
HDassert(type);
|
||
|
||
/* 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")
|
||
|
||
/* Locate message of correct type */
|
||
for(idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++)
|
||
if(type == idx_msg->type)
|
||
break;
|
||
|
||
if(idx == oh->nmesgs)
|
||
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message type not found")
|
||
|
||
/* Set return value */
|
||
*flags = idx_msg->flags;
|
||
|
||
done:
|
||
if(oh && H5O_unprotect(loc, 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)
|
||
} /* end H5O_msg_get_flags() */
|