#include "H5Omodule.h"
#include "H5private.h"
#include "H5Aprivate.h"
#include "H5Eprivate.h"
#include "H5Fprivate.h"
#include "H5Iprivate.h"
#include "H5MMprivate.h"
#include "H5Opkg.h"
#include "H5SMprivate.h"
typedef struct {
H5F_t *f;
int sequence;
unsigned nfailed;
H5O_operator_t op;
void *op_data;
hbool_t adj_link;
} H5O_iter_rm_t;
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,
unsigned sequence, unsigned *oh_modified, void *_udata);
static herr_t H5O__copy_mesg(H5F_t *f, H5O_t *oh, size_t idx,
const H5O_msg_class_t *type, const void *mesg, unsigned mesg_flags,
unsigned update_flags);
herr_t
H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
unsigned update_flags, void *mesg)
{
H5O_t *oh = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
HDassert(type_id < NELMTS(H5O_msg_class_g));
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
HDassert(mesg);
if(NULL == (oh = H5O_pin(loc)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
if(H5O_msg_append_oh(loc->file, 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)
}
herr_t
H5O_msg_append_oh(H5F_t *f, H5O_t *oh, unsigned type_id,
unsigned mesg_flags, unsigned update_flags, void *mesg)
{
const H5O_msg_class_t *type;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(oh);
HDassert(H5O_ATTR_ID != type_id);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
HDassert(mesg);
if(H5O__msg_append_real(f, 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)
}
herr_t
H5O__msg_append_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
unsigned mesg_flags, unsigned update_flags, void *mesg)
{
size_t idx;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(oh);
HDassert(type);
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
HDassert(mesg);
if(H5O__msg_alloc(f, oh, type, &mesg_flags, mesg, &idx) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "unable to create new message")
if(H5O__copy_mesg(f, 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
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_msg_write(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
unsigned update_flags, void *mesg)
{
H5O_t *oh = NULL;
const H5O_msg_class_t *type;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
HDassert(loc->file);
HDassert(H5F_addr_defined(loc->addr));
HDassert(H5O_ATTR_ID != type_id);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
HDassert(mesg);
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
if(NULL == (oh = H5O_pin(loc)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
if(H5O__msg_write_real(loc->file, 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)
}
herr_t
H5O_msg_write_oh(H5F_t *f, H5O_t *oh, unsigned type_id, unsigned mesg_flags,
unsigned update_flags, void *mesg)
{
const H5O_msg_class_t *type;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_TAG(oh->cache_info.addr, FAIL)
HDassert(f);
HDassert(oh);
HDassert(H5O_ATTR_ID != type_id);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
HDassert(mesg);
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
if(H5O__msg_write_real(f, 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)
}
herr_t
H5O__msg_write_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
unsigned mesg_flags, unsigned update_flags, void *mesg)
{
H5O_mesg_t *idx_msg;
size_t idx;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(oh);
HDassert(type);
HDassert(type != H5O_MSG_ATTR);
HDassert(mesg);
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
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")
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")
else if((idx_msg->flags & H5O_MSG_FLAG_SHARED) || (idx_msg->flags & H5O_MSG_FLAG_SHAREABLE)) {
htri_t status;
HDassert(((H5O_shared_t *)idx_msg->native)->type != H5O_SHARE_TYPE_COMMITTED);
HDassert(!(mesg_flags & H5O_MSG_FLAG_DONTSHARE));
if(H5SM_delete(f, oh, (H5O_shared_t *)idx_msg->native) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete message from SOHM index")
if((status = H5SM_try_share(f, ((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")
}
if(H5O__copy_mesg(f, 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
done:
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, void *mesg)
{
H5O_t *oh = NULL;
void *ret_value = NULL;
FUNC_ENTER_NOAPI_TAG(loc->addr, NULL)
HDassert(loc);
HDassert(loc->file);
HDassert(H5F_addr_defined(loc->addr));
HDassert(type_id < NELMTS(H5O_msg_class_g));
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header")
if(NULL == (ret_value = H5O_msg_read_oh(loc->file, oh, type_id, mesg)))
HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header message")
done:
if(oh && H5O_unprotect(loc, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
void *
H5O_msg_read_oh(H5F_t *f, H5O_t *oh, unsigned type_id, void *mesg)
{
const H5O_msg_class_t *type;
unsigned idx;
void *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert(f);
HDassert(oh);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
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")
H5O_LOAD_NATIVE(f, 0, oh, &(oh->mesg[idx]), NULL)
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)
}
herr_t
H5O_msg_reset(unsigned type_id, void *native)
{
const H5O_msg_class_t *type;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
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)
}
static herr_t
H5O__msg_reset_real(const H5O_msg_class_t *type, void *native)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(type);
if(native) {
if(type->reset) {
if((type->reset)(native) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "reset method failed")
}
else
HDmemset(native, 0, type->native_size);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5O_msg_free(unsigned type_id, void *mesg)
{
const H5O_msg_class_t *type;
void *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
ret_value = H5O__msg_free_real(type, mesg);
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O__msg_free_mesg(H5O_mesg_t *mesg)
{
FUNC_ENTER_PACKAGE_NOERR
HDassert(mesg);
mesg->native = H5O__msg_free_real(mesg->type, mesg->native);
FUNC_LEAVE_NOAPI(SUCCEED)
}
void *
H5O__msg_free_real(const H5O_msg_class_t *type, void *msg_native)
{
FUNC_ENTER_PACKAGE_NOERR
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);
}
FUNC_LEAVE_NOAPI(NULL)
}
void *
H5O_msg_copy(unsigned type_id, const void *mesg, void *dst)
{
const H5O_msg_class_t *type;
void *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(mesg);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
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)
}
int
H5O_msg_count(const H5O_loc_t *loc, unsigned type_id)
{
H5O_t *oh = NULL;
const H5O_msg_class_t *type;
unsigned msg_count;
int ret_value = FAIL;
FUNC_ENTER_NOAPI(FAIL)
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];
HDassert(type);
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
msg_count = H5O_msg_count_real(oh, type);
H5_CHECKED_ASSIGN(ret_value, int, msg_count, unsigned);
done:
if(oh && H5O_unprotect(loc, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
}
unsigned
H5O_msg_count_real(const H5O_t *oh, const H5O_msg_class_t *type)
{
unsigned u;
unsigned ret_value = 0;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(oh);
HDassert(type);
for(u = ret_value = 0; u < oh->nmesgs; u++)
if(oh->mesg[u].type == type)
ret_value++;
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5O_msg_exists(const H5O_loc_t *loc, unsigned type_id)
{
H5O_t *oh = NULL;
htri_t ret_value = FAIL;
FUNC_ENTER_NOAPI_TAG(loc->addr, FAIL)
HDassert(loc);
HDassert(loc->file);
HDassert(type_id < NELMTS(H5O_msg_class_g));
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
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, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
htri_t
H5O_msg_exists_oh(const H5O_t *oh, unsigned type_id)
{
const H5O_msg_class_t *type;
unsigned u;
htri_t ret_value = FALSE;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(oh);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
for(u = 0; u < oh->nmesgs; u++)
if(type == oh->mesg[u].type)
HGOTO_DONE(TRUE)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_msg_remove(const H5O_loc_t *loc, unsigned type_id, int sequence, hbool_t adj_link)
{
H5O_t *oh = NULL;
const H5O_msg_class_t *type;
herr_t ret_value = FAIL;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
HDassert(loc->file);
HDassert(H5F_addr_defined(loc->addr));
HDassert(H5O_ATTR_ID != type_id);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
if(NULL == (oh = H5O_pin(loc)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
if((ret_value = H5O__msg_remove_real(loc->file, oh, type, sequence, NULL, NULL, adj_link)) < 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)
}
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)
{
H5O_t *oh = NULL;
const H5O_msg_class_t *type;
herr_t ret_value = FAIL;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
HDassert(loc->file);
HDassert(H5F_addr_defined(loc->addr));
HDassert(H5O_ATTR_ID != type_id);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
if(NULL == (oh = H5O_pin(loc)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
if((ret_value = H5O__msg_remove_real(loc->file, oh, type, sequence, op, op_data, adj_link)) < 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)
}
static herr_t
H5O__msg_remove_cb(H5O_t *oh, H5O_mesg_t *mesg, unsigned sequence,
unsigned *oh_modified, void *_udata)
{
H5O_iter_rm_t *udata = (H5O_iter_rm_t *)_udata;
htri_t try_remove = FALSE;
herr_t ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC
HDassert(mesg);
if(udata->op) {
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")
}
else {
if((int)sequence == udata->sequence || H5O_ALL == udata->sequence)
try_remove = TRUE;
}
if(try_remove) {
if(H5O_release_mesg(udata->f, oh, mesg, udata->adj_link) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to release message")
*oh_modified = H5O_MODIFY_CONDENSE;
if(udata->sequence == H5O_FIRST || udata->sequence != H5O_ALL)
HGOTO_DONE(H5_ITER_STOP)
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
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)
{
H5O_iter_rm_t udata;
H5O_mesg_operator_t op;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(oh);
HDassert(type);
if(0 == (H5F_INTENT(f) & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file")
udata.f = f;
udata.sequence = sequence;
udata.nfailed = 0;
udata.op = app_op;
udata.op_data = op_data;
udata.adj_link = adj_link;
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) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "error iterating over messages")
if(udata.nfailed)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to remove constant message(s)")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_msg_iterate(const H5O_loc_t *loc, unsigned type_id,
const H5O_mesg_operator_t *op, void *op_data)
{
H5O_t *oh = NULL;
const H5O_msg_class_t *type;
herr_t ret_value = FAIL;
FUNC_ENTER_NOAPI(FAIL)
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];
HDassert(type);
HDassert(op);
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
if((ret_value = H5O__msg_iterate_real(loc->file, oh, type, op, op_data)) < 0)
HERROR(H5E_OHDR, H5E_BADITER, "unable to iterate over object header messages");
done:
if(oh && H5O_unprotect(loc, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
}
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)
{
H5O_mesg_t *idx_msg;
unsigned idx;
unsigned sequence;
unsigned oh_modified = 0;
herr_t ret_value = H5_ITER_CONT;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(oh);
HDassert(type);
HDassert(op);
HDassert(op->u.app_op);
for(sequence = 0, idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs && !ret_value; idx++, idx_msg++) {
if(type == idx_msg->type) {
H5O_LOAD_NATIVE(f, 0, oh, idx_msg, FAIL)
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);
if(ret_value != 0)
break;
sequence++;
}
}
if(ret_value < 0)
HERROR(H5E_OHDR, H5E_CANTLIST, "iterator function failed");
done:
if(oh_modified) {
if(oh_modified & H5O_MODIFY_CONDENSE)
if(H5O_condense_header(f, oh) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't pack object header")
if(H5O_touch_oh(f, oh, FALSE) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
if(H5AC_mark_entry_dirty(oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
}
FUNC_LEAVE_NOAPI(ret_value)
}
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;
size_t ret_value = 0;
FUNC_ENTER_NOAPI(0)
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
HDassert(type->raw_size);
HDassert(f);
HDassert(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)
}
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;
H5P_genplist_t *ocpl;
uint8_t oh_flags;
size_t ret_value = 0;
FUNC_ENTER_NOAPI(0)
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
HDassert(type->raw_size);
HDassert(f);
HDassert(mesg);
if(NULL == (ocpl = (H5P_genplist_t *)H5I_object(ocpl_id)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, 0, "not a property list")
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")
if((ret_value = (type->raw_size)(f, FALSE, mesg)) == 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message")
ret_value += extra_raw;
ret_value = (size_t)H5O_ALIGN_F(f, ret_value);
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)
}
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;
size_t ret_value = 0;
FUNC_ENTER_NOAPI(0)
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
HDassert(type->raw_size);
HDassert(f);
HDassert(mesg);
if((ret_value = (type->raw_size)(f, FALSE, mesg)) == 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, 0, "unable to determine size of message")
ret_value += extra_raw;
ret_value = (size_t)H5O_ALIGN_OH(oh, ret_value);
ret_value += (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5O_msg_can_share(unsigned type_id, const void *mesg)
{
const H5O_msg_class_t *type;
htri_t ret_value = FAIL;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
HDassert(mesg);
if(type->can_share)
ret_value = (type->can_share)(mesg);
else {
ret_value = (type->share_flags & H5O_SHARE_IS_SHARABLE) ? TRUE : FALSE;
}
HDassert((type->post_copy_file && type->copy_file) || ret_value == FALSE);
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5O_msg_can_share_in_ohdr(unsigned type_id)
{
const H5O_msg_class_t *type;
htri_t ret_value = FAIL;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
ret_value = (type->share_flags & H5O_SHARE_IN_OHDR) ? TRUE : FALSE;
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5O_msg_is_shared(unsigned type_id, const void *mesg)
{
const H5O_msg_class_t *type;
htri_t ret_value = FAIL;
FUNC_ENTER_NOAPI_NOINIT_NOERR
#ifdef H5O_ENABLE_BOGUS
if(type_id >= NELMTS(H5O_msg_class_g))
ret_value = FALSE;
else
#endif
{
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
HDassert(mesg);
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)
}
herr_t
H5O_msg_set_share(unsigned type_id, const H5O_shared_t *share, void *mesg)
{
const H5O_msg_class_t *type;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE);
HDassert(mesg);
HDassert(share);
HDassert(share->type != H5O_SHARE_TYPE_UNSHARED);
if(type->set_share) {
if((type->set_share)(mesg, share) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information")
}
else {
if(H5O_set_shared((H5O_shared_t *)mesg, share) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_msg_reset_share(unsigned H5_ATTR_NDEBUG_UNUSED type_id, void *mesg)
{
const H5O_msg_class_t *type;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE);
HDassert(mesg);
HDmemset((H5O_shared_t *)mesg, 0, sizeof(H5O_shared_t));
FUNC_LEAVE_NOAPI(SUCCEED)
}
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;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
HDassert(mesg);
HDassert(crt_idx);
if(type->get_crt_index) {
if((type->get_crt_index)(mesg, crt_idx) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve creation index")
}
else
*crt_idx = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
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;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
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)
}
void *
H5O_msg_decode(H5F_t *f, H5O_t *open_oh, unsigned type_id, size_t buf_size,
const unsigned char *buf)
{
const H5O_msg_class_t *type;
unsigned ioflags = 0;
void *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(f);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
if(NULL == (ret_value = (type->decode)(f, open_oh, 0, &ioflags, buf_size, buf)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode message")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
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)
{
void *ret_value = NULL;
FUNC_ENTER_PACKAGE
HDassert(type);
HDassert(type->copy_file);
HDassert(file_src);
HDassert(native_src);
HDassert(file_dst);
HDassert(recompute_size);
HDassert(cpy_info);
if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, recompute_size, mesg_flags, cpy_info, udata)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object header message to file")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O__msg_alloc(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
unsigned *mesg_flags, void *native, size_t *mesg_idx)
{
size_t new_idx;
htri_t shared_mesg;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(oh);
HDassert(mesg_flags);
HDassert(!(*mesg_flags & H5O_MSG_FLAG_SHARED));
HDassert(type);
HDassert(native);
HDassert(mesg_idx);
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) {
if(type->link && (type->link)(f, oh, native) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared message ref count")
*mesg_flags |= H5O_MSG_FLAG_SHARED;
}
else {
if(H5SM_try_share(f, oh, 0, type->id, native, mesg_flags) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "error determining if message should be shared")
}
if(H5O__alloc(f, oh, type, native, &new_idx) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for message")
if(type->get_crt_index) {
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")
}
*mesg_idx = new_idx;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5O__copy_mesg(H5F_t *f, 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;
H5O_mesg_t *idx_msg = &oh->mesg[idx];
hbool_t chk_dirtied = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(oh);
HDassert(type);
HDassert(type->copy);
HDassert(mesg);
if(NULL == (chk_proxy = H5O__chunk_protect(f, oh, idx_msg->chunkno)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header chunk")
H5O__msg_reset_real(type, idx_msg->native);
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")
idx_msg->flags = (uint8_t)mesg_flags;
idx_msg->dirty = TRUE;
chk_dirtied = TRUE;
if(H5O__chunk_unprotect(f, chk_proxy, chk_dirtied) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
chk_proxy = NULL;
if(update_flags & H5O_UPDATE_TIME)
if(H5O_touch_oh(f, oh, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
done:
if(chk_proxy && H5O__chunk_unprotect(f, chk_proxy, chk_dirtied) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_msg_delete(H5F_t *f, H5O_t *open_oh, unsigned type_id, void *mesg)
{
const H5O_msg_class_t *type;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(type_id < NELMTS(H5O_msg_class_g));
type = H5O_msg_class_g[type_id];
HDassert(type);
if((type->del) && (type->del)(f, 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)
}
herr_t
H5O__delete_mesg(H5F_t *f, H5O_t *oh, H5O_mesg_t *mesg)
{
const H5O_msg_class_t *type = mesg->type;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(mesg);
HDassert(oh);
if(type->del) {
H5O_LOAD_NATIVE(f, H5O_DECODEIO_NOCHANGE, oh, mesg, FAIL)
if((type->del)(f, oh, mesg->native) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_msg_flush(H5F_t *f, H5O_t *oh, H5O_mesg_t *mesg)
{
uint8_t *p;
unsigned msg_id;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(oh);
p = mesg->raw - H5O_SIZEOF_MSGHDR_OH(oh);
if(mesg->type == H5O_MSG_UNKNOWN)
msg_id = *(H5O_unknown_t *)(mesg->native);
else
msg_id = (uint8_t)mesg->type->id;
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;
if(oh->version == H5O_VERSION_1) {
*p++ = 0;
*p++ = 0;
*p++ = 0;
}
else {
if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
UINT16ENCODE(p, mesg->crt_idx);
}
HDassert(p == mesg->raw);
#ifndef NDEBUG
if(H5O_NULL_ID == msg_id)
HDassert(oh->chunk[mesg->chunkno].gap == 0);
else
HDassert(mesg->native);
#endif
if(mesg->native && mesg->type != H5O_MSG_UNKNOWN) {
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
{
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
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")
}
mesg->dirty = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_flush_msgs(H5F_t *f, H5O_t *oh)
{
H5O_mesg_t *curr_msg;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(oh);
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")
if(oh->nmesgs != u)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "corrupt object header - too few messages")
#ifndef NDEBUG
oh->ndecode_dirtied = 0;
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_msg_get_flags(const H5O_loc_t *loc, unsigned type_id, uint8_t *flags)
{
H5O_t *oh = NULL;
const H5O_msg_class_t *type;
H5O_mesg_t *idx_msg;
unsigned idx;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
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];
HDassert(type);
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
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")
*flags = idx_msg->flags;
done:
if(oh && H5O_unprotect(loc, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
}