#include "H5Omodule.h"
#include "H5private.h"
#include "H5CXprivate.h"
#include "H5Eprivate.h"
#include "H5Fprivate.h"
#include "H5FLprivate.h"
#include "H5FOprivate.h"
#include "H5Iprivate.h"
#include "H5Lprivate.h"
#include "H5MFprivate.h"
#include "H5MMprivate.h"
#include "H5Opkg.h"
typedef struct {
hid_t obj_id;
H5G_loc_t *start_loc;
H5SL_t *visited;
H5O_iterate_t op;
void *op_data;
unsigned fields;
} H5O_iter_visit_ud_t;
static herr_t H5O__delete_oh(H5F_t *f, H5O_t *oh);
static herr_t H5O__obj_type_real(const H5O_t *oh, H5O_type_t *obj_type);
static herr_t H5O__get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr);
static herr_t H5O__free_visit_visited(void *item, void *key,
void *operator_data);
static herr_t H5O__visit_cb(hid_t group, const char *name, const H5L_info_t *linfo,
void *_udata);
static const H5O_obj_class_t *H5O__obj_class_real(const H5O_t *oh);
hbool_t H5_PKG_INIT_VAR = FALSE;
const H5O_msg_class_t *const H5O_msg_class_g[] = {
H5O_MSG_NULL,
H5O_MSG_SDSPACE,
H5O_MSG_LINFO,
H5O_MSG_DTYPE,
H5O_MSG_FILL,
H5O_MSG_FILL_NEW,
H5O_MSG_LINK,
H5O_MSG_EFL,
H5O_MSG_LAYOUT,
#ifdef H5O_ENABLE_BOGUS
H5O_MSG_BOGUS_VALID,
#else
NULL,
#endif
H5O_MSG_GINFO,
H5O_MSG_PLINE,
H5O_MSG_ATTR,
H5O_MSG_NAME,
H5O_MSG_MTIME,
H5O_MSG_SHMESG,
H5O_MSG_CONT,
H5O_MSG_STAB,
H5O_MSG_MTIME_NEW,
H5O_MSG_BTREEK,
H5O_MSG_DRVINFO,
H5O_MSG_AINFO,
H5O_MSG_REFCOUNT,
H5O_MSG_FSINFO,
H5O_MSG_MDCI,
H5O_MSG_UNKNOWN
};
const unsigned H5O_obj_ver_bounds[] = {
H5O_VERSION_1,
H5O_VERSION_2,
H5O_VERSION_LATEST
};
H5FL_DEFINE(H5O_t);
H5FL_SEQ_DEFINE(H5O_mesg_t);
H5FL_SEQ_DEFINE(H5O_chunk_t);
H5FL_BLK_DEFINE(chunk_image);
H5FL_SEQ_EXTERN(H5O_cont_t);
H5FL_EXTERN(time_t);
H5FL_EXTERN(H5_obj_t);
static const H5O_obj_class_t *const H5O_obj_class_g[] = {
H5O_OBJ_DATATYPE,
H5O_OBJ_DATASET,
H5O_OBJ_GROUP,
};
herr_t
H5O__init_package(void)
{
FUNC_ENTER_PACKAGE_NOERR
HDcompile_assert(H5O_MSG_TYPES == NELMTS(H5O_msg_class_g));
HDcompile_assert(sizeof(H5O_fheap_id_t) == H5O_FHEAP_ID_LEN);
HDcompile_assert(H5O_UNKNOWN_ID < H5O_MSG_TYPES);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5O_set_version(H5F_t *f, H5O_t *oh, uint8_t oh_flags, hbool_t store_msg_crt_idx)
{
uint8_t version;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(oh);
if(store_msg_crt_idx || (oh_flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED))
version = H5O_VERSION_LATEST;
else
version = H5O_VERSION_1;
version = (uint8_t)MAX(version, (uint8_t)H5O_obj_ver_bounds[H5F_LOW_BOUND(f)]);
if(version > H5O_obj_ver_bounds[H5F_HIGH_BOUND(f)])
HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "object header version out of bounds")
oh->version = version;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_create(H5F_t *f, size_t size_hint, size_t initial_rc, hid_t ocpl_id,
H5O_loc_t *loc)
{
H5P_genplist_t *oc_plist;
H5O_t *oh = NULL;
herr_t ret_value = SUCCEED;
haddr_t oh_addr;
size_t oh_size;
uint8_t oh_flags;
unsigned insert_flags = H5AC__NO_FLAGS_SET;
hbool_t store_msg_crt_idx;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(loc);
HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
oh = H5O__create_ohdr(f, ocpl_id);
if(NULL == oh)
HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "Can't instantiate object header")
if(H5O__apply_ohdr(f, oh, ocpl_id, size_hint, initial_rc, loc) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "Can't apply object header to file")
done:
if((FAIL == ret_value) && (NULL != oh) && (H5O__free(oh) < 0))
HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "can't delete object header")
FUNC_LEAVE_NOAPI(ret_value)
}
H5O_t *
H5O__create_ohdr(H5F_t *f, hid_t ocpl_id)
{
H5P_genplist_t *oc_plist;
H5O_t *oh = NULL;
uint8_t oh_flags;
H5O_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(f);
HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
if(0 == (H5F_INTENT(f) & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "no write intent on file")
oh = H5FL_CALLOC(H5O_t);
if(NULL == oh)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
oc_plist = (H5P_genplist_t *)H5I_object(ocpl_id);
if(NULL == oc_plist)
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, NULL, "not a property list")
if(H5P_DATASET_CREATE_DEFAULT == ocpl_id) {
if(H5CX_get_ohdr_flags(&oh_flags) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get object header flags")
}
else {
if(H5P_get(oc_plist, H5O_CRT_OHDR_FLAGS_NAME, &oh_flags) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get object header flags")
}
if(H5O_set_version(f, oh, oh_flags, H5F_STORE_MSG_CRT_IDX(f)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, NULL, "can't set version of object header")
oh->flags = oh_flags;
ret_value = oh;
done:
if((NULL == ret_value) && (NULL != oh) && (H5O__free(oh) < 0))
HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, NULL, "can't delete object header")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O__apply_ohdr(H5F_t *f, H5O_t *oh, hid_t ocpl_id, size_t size_hint, size_t initial_rc, H5O_loc_t *loc_out)
{
haddr_t oh_addr;
size_t oh_size;
H5P_genplist_t *oc_plist = NULL;
unsigned insert_flags = H5AC__NO_FLAGS_SET;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(loc_out);
HDassert(oh);
HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
size_hint = H5O_ALIGN_F(f, MAX(H5O_MIN_SIZE, size_hint));
oh->sizeof_size = H5F_SIZEOF_SIZE(f);
oh->sizeof_addr = H5F_SIZEOF_ADDR(f);
oh->swmr_write = !!(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE);
#ifdef H5O_ENABLE_BAD_MESG_COUNT
if(H5P_exist_plist(oc_plist, H5O_BAD_MESG_COUNT_NAME) > 0)
if(H5P_get(oc_plist, H5O_BAD_MESG_COUNT_NAME, &oh->store_bad_mesg_count) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get bad message count flag")
#endif
if(oh->swmr_write) {
if(NULL == (oh->proxy = H5AC_proxy_entry_create()))
HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create object header proxy")
} else {
oh->proxy = NULL;
}
oc_plist = (H5P_genplist_t *)H5I_object(ocpl_id);
if(NULL == oc_plist)
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a property list")
if(oh->version > H5O_VERSION_1) {
if(oh->flags & H5O_HDR_STORE_TIMES)
oh->atime = oh->mtime = oh->ctime = oh->btime = H5_now();
else
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
if(H5F_STORE_MSG_CRT_IDX(f))
oh->flags |= H5O_HDR_ATTR_CRT_ORDER_TRACKED;
if(H5P_get(oc_plist, H5O_CRT_ATTR_MAX_COMPACT_NAME, &oh->max_compact) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get max. # of compact attributes")
if(H5P_get(oc_plist, H5O_CRT_ATTR_MIN_DENSE_NAME, &oh->min_dense) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get min. # of dense attributes")
if(oh->max_compact != H5O_CRT_ATTR_MAX_COMPACT_DEF || oh->min_dense != H5O_CRT_ATTR_MIN_DENSE_DEF)
oh->flags |= H5O_HDR_ATTR_STORE_PHASE_CHANGE;
#if H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T
if(size_hint > 4294967295UL)
oh->flags |= H5O_HDR_CHUNK0_8;
else
#endif
if(size_hint > 65535)
oh->flags |= H5O_HDR_CHUNK0_4;
else if(size_hint > 255)
oh->flags |= H5O_HDR_CHUNK0_2;
} else {
oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
}
oh_size = (size_t)H5O_SIZEOF_HDR(oh) + size_hint;
if(HADDR_UNDEF == (oh_addr = H5MF_alloc(f, H5FD_MEM_OHDR, (hsize_t)oh_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header")
oh->nchunks = oh->alloc_nchunks = 1;
if(NULL == (oh->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->alloc_nchunks)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
oh->chunk[0].addr = oh_addr;
oh->chunk[0].size = oh_size;
oh->chunk[0].gap = 0;
if(NULL == (oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, oh_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
oh->chunk[0].chunk_proxy = NULL;
if(oh->version > H5O_VERSION_1)
H5MM_memcpy(oh->chunk[0].image, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
oh->nmesgs = 1;
oh->alloc_nmesgs = H5O_NMESGS;
if(NULL == (oh->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh->alloc_nmesgs)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
oh->mesg[0].type = H5O_MSG_NULL;
oh->mesg[0].dirty = TRUE;
oh->mesg[0].native = NULL;
oh->mesg[0].raw = oh->chunk[0].image + (H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)) + H5O_SIZEOF_MSGHDR_OH(oh);
oh->mesg[0].raw_size = size_hint - (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
oh->mesg[0].chunkno = 0;
if(initial_rc > 0) {
oh->rc = initial_rc;
insert_flags |= H5AC__PIN_ENTRY_FLAG;
}
H5_BEGIN_TAG(oh_addr);
if(H5AC_insert_entry(f, H5AC_OHDR, oh_addr, oh, insert_flags) < 0)
HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header")
oh = NULL;
H5_END_TAG
loc_out->file = f;
loc_out->addr = oh_addr;
if(H5O_open(loc_out) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object header")
done:
FUNC_LEAVE_NOAPI(ret_value);
}
herr_t
H5O_open(H5O_loc_t *loc)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
HDassert(loc->file);
#ifdef H5O_DEBUG
if(H5DEBUG(O))
HDfprintf(H5DEBUG(O), "> %a\n", loc->addr);
#endif
if(loc->holding_file)
loc->holding_file = FALSE;
else
H5F_INCR_NOPEN_OBJS(loc->file);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5O_open_name(const H5G_loc_t *loc, const char *name, hbool_t app_ref)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_NOAPI(H5I_INVALID_HID)
HDassert(loc);
HDassert(name && *name);
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find(loc, name, &obj_loc) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5I_INVALID_HID, "object not found")
loc_found = TRUE;
if((ret_value = H5O__open_by_loc(&obj_loc, app_ref)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
done:
if(ret_value < 0 && loc_found)
if(H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5I_INVALID_HID, "can't free location")
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5O__open_by_idx(const H5G_loc_t *loc, const char *name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_PACKAGE
HDassert(loc);
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find_by_idx(loc, name, idx_type, order, n, &obj_loc) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5I_INVALID_HID, "group not found")
loc_found = TRUE;
if((ret_value = H5O__open_by_loc(&obj_loc, TRUE)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
done:
if(ret_value < 0 && loc_found)
if(H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5I_INVALID_HID, "can't free location")
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5O__open_by_addr(const H5G_loc_t *loc, haddr_t addr)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_PACKAGE
HDassert(loc);
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
obj_loc.oloc->addr = addr;
obj_loc.oloc->file = loc->oloc->file;
H5G_name_reset(obj_loc.path);
if((ret_value = H5O__open_by_loc(&obj_loc, TRUE)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5O__open_by_loc(const H5G_loc_t *obj_loc, hbool_t app_ref)
{
const H5O_obj_class_t *obj_class;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_PACKAGE
HDassert(obj_loc);
if(NULL == (obj_class = H5O__obj_class(obj_loc->oloc)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5I_INVALID_HID, "unable to determine object class")
HDassert(obj_class->open);
if((ret_value = obj_class->open(obj_loc, app_ref)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, H5I_INVALID_HID, "unable to open object")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_close(H5O_loc_t *loc, hbool_t *file_closed )
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
HDassert(loc->file);
HDassert(H5F_NOPEN_OBJS(loc->file) > 0);
if(file_closed)
*file_closed = FALSE;
H5F_DECR_NOPEN_OBJS(loc->file);
#ifdef H5O_DEBUG
if(H5DEBUG(O)) {
if(H5F_FILE_ID(loc->file)< 0 && 1 == H5F_NREFS(loc->file))
HDfprintf(H5DEBUG(O), "< %a auto %lu remaining\n", loc->addr, (unsigned long)H5F_NOPEN_OBJS(loc->file));
else
HDfprintf(H5DEBUG(O), "< %a\n", loc->addr);
}
#endif
if(H5F_NOPEN_OBJS(loc->file) == H5F_NMOUNTS(loc->file))
if(H5F_try_close(loc->file, file_closed) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCLOSEFILE, FAIL, "problem attempting file close")
if(H5O_loc_free(loc) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "problem attempting to free location")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5O__link_oh(H5F_t *f, int adjust, H5O_t *oh, hbool_t *deleted)
{
haddr_t addr = H5O_OH_GET_ADDR(oh);
int ret_value = -1;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(oh);
HDassert(deleted);
if(adjust) {
if(adjust < 0) {
if((unsigned)(-adjust) > oh->nlink)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, (-1), "link count would be negative")
oh->nlink = (unsigned)((int)oh->nlink + adjust);
if(H5AC_mark_entry_dirty(oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, (-1), "unable to mark object header as dirty")
if(oh->nlink == 0) {
if(H5FO_opened(f, addr) != NULL) {
if(H5FO_mark(f, addr, TRUE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, (-1), "can't mark object for deletion")
}
else {
*deleted = TRUE;
}
}
}
else {
if(0 == oh->nlink) {
if(H5FO_marked(f, addr)) {
if(H5FO_mark(f, addr, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, (-1), "can't mark object for deletion")
}
}
oh->nlink = (unsigned)((int)oh->nlink + adjust);
if(H5AC_mark_entry_dirty(oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, (-1), "unable to mark object header as dirty")
}
if(oh->version > H5O_VERSION_1) {
if(oh->has_refcount_msg) {
if(oh->nlink <= 1) {
if(H5O__msg_remove_real(f, oh, H5O_MSG_REFCOUNT, H5O_ALL, NULL, NULL, TRUE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, (-1), "unable to delete refcount message")
oh->has_refcount_msg = FALSE;
}
else {
H5O_refcount_t refcount = oh->nlink;
if(H5O__msg_write_real(f, oh, H5O_MSG_REFCOUNT, H5O_MSG_FLAG_DONTSHARE, 0, &refcount) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUPDATE, (-1), "unable to update refcount message")
}
}
else {
if(oh->nlink > 1) {
H5O_refcount_t refcount = oh->nlink;
if(H5O__msg_append_real(f, oh, H5O_MSG_REFCOUNT, H5O_MSG_FLAG_DONTSHARE, 0, &refcount) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, (-1), "unable to create new refcount message")
oh->has_refcount_msg = TRUE;
}
}
}
}
ret_value = (int)oh->nlink;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5O_link(const H5O_loc_t *loc, int adjust)
{
H5O_t *oh = NULL;
hbool_t deleted = FALSE;
int ret_value = -1;
FUNC_ENTER_NOAPI_TAG(loc->addr, FAIL)
HDassert(loc);
HDassert(loc->file);
HDassert(H5F_addr_defined(loc->addr));
if(NULL == (oh = H5O_pin(loc)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
if((ret_value = H5O__link_oh(loc->file, adjust, oh, &deleted)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust object link count")
done:
if(oh && H5O_unpin(oh) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
if(ret_value >= 0 && deleted && H5O_delete(loc->file, loc->addr) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
H5O_t *
H5O_protect(const H5O_loc_t *loc, unsigned prot_flags, hbool_t pin_all_chunks)
{
H5O_t *oh = NULL;
H5O_cache_ud_t udata;
H5O_cont_msgs_t cont_msg_info;
unsigned file_intent;
H5O_t *ret_value = NULL;
FUNC_ENTER_NOAPI_TAG(loc->addr, NULL)
HDassert(loc);
HDassert(loc->file);
HDassert((prot_flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
if(!H5F_addr_defined(loc->addr))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "address undefined")
file_intent = H5F_INTENT(loc->file);
if((0 == (prot_flags & H5AC__READ_ONLY_FLAG)) && (0 == (file_intent & H5F_ACC_RDWR)))
HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "no write intent on file")
udata.made_attempt = FALSE;
udata.v1_pfx_nmesgs = 0;
udata.chunk0_size = 0;
udata.oh = NULL;
udata.free_oh = FALSE;
udata.common.f = loc->file;
udata.common.file_intent = file_intent;
udata.common.merged_null_msgs = 0;
HDmemset(&cont_msg_info, 0, sizeof(cont_msg_info));
udata.common.cont_msg_info = &cont_msg_info;
udata.common.addr = loc->addr;
if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, H5AC_OHDR, loc->addr, &udata, prot_flags)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header")
if(cont_msg_info.nmsgs > 0) {
size_t curr_msg;
H5O_chk_cache_ud_t chk_udata;
HDassert(udata.made_attempt == TRUE);
HDassert(cont_msg_info.msgs);
chk_udata.decoding = TRUE;
chk_udata.oh = oh;
chk_udata.chunkno = UINT_MAX;
chk_udata.common.f = loc->file;
chk_udata.common.file_intent = file_intent;
chk_udata.common.merged_null_msgs = udata.common.merged_null_msgs;
chk_udata.common.cont_msg_info = &cont_msg_info;
curr_msg = 0;
while(curr_msg < cont_msg_info.nmsgs) {
H5O_chunk_proxy_t *chk_proxy;
#ifndef NDEBUG
size_t chkcnt = oh->nchunks;
#endif
chk_udata.common.addr = cont_msg_info.msgs[curr_msg].addr;
chk_udata.size = cont_msg_info.msgs[curr_msg].size;
if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(loc->file, H5AC_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, &chk_udata, prot_flags)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header chunk")
HDassert(chk_proxy->oh == oh);
HDassert(chk_proxy->chunkno == chkcnt);
HDassert(oh->nchunks == (chkcnt + 1));
if(H5AC_unprotect(loc->file, H5AC_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, chk_proxy, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header chunk")
curr_msg++;
}
cont_msg_info.msgs = (H5O_cont_t *)H5FL_SEQ_FREE(H5O_cont_t, cont_msg_info.msgs);
udata.common.merged_null_msgs = chk_udata.common.merged_null_msgs;
}
if(udata.made_attempt) {
#ifdef H5_STRICT_FORMAT_CHECKS
if(oh->version == H5O_VERSION_1 &&
(oh->nmesgs + udata.common.merged_null_msgs) != udata.v1_pfx_nmesgs)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - incorrect # of messages")
#endif
}
#ifdef H5O_DEBUG
H5O_assert(oh);
#endif
if(pin_all_chunks && oh->nchunks > 1) {
unsigned u;
HDassert(oh->swmr_write);
for(u = 1; u < oh->nchunks; u++) {
H5O_chunk_proxy_t *chk_proxy;
if(NULL == (chk_proxy = H5O__chunk_protect(loc->file, oh, u)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header chunk")
if(H5AC_pin_protected_entry(chk_proxy) < 0 )
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, NULL, "unable to pin object header chunk")
if(H5O__chunk_unprotect(loc->file, chk_proxy, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to unprotect object header chunk")
oh->chunk[u].chunk_proxy = chk_proxy;
}
oh->chunks_pinned = TRUE;
}
ret_value = oh;
done:
if(ret_value == NULL && oh)
if(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)
}
H5O_t *
H5O_pin(const H5O_loc_t *loc)
{
H5O_t *oh = NULL;
H5O_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(loc);
if(NULL == (oh = H5O_protect(loc, H5AC__NO_FLAGS_SET, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header")
if(H5O__inc_rc(oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "unable to increment reference count on object header")
ret_value = oh;
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(ret_value)
}
herr_t
H5O_unpin(H5O_t *oh)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(oh);
if(H5O__dec_rc(oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement reference count on object header")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_unprotect(const H5O_loc_t *loc, H5O_t *oh, unsigned oh_flags)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
HDassert(oh);
if(oh->chunks_pinned && oh->nchunks > 1) {
unsigned u;
HDassert(oh->swmr_write);
for(u = 1; u < oh->nchunks; u++) {
if(NULL != oh->chunk[u].chunk_proxy) {
if(H5AC_unpin_entry(oh->chunk[u].chunk_proxy) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header chunk")
oh->chunk[u].chunk_proxy = NULL;
}
}
oh->chunks_pinned = FALSE;
}
if(H5AC_unprotect(loc->file, H5AC_OHDR, oh->chunk[0].addr, oh, oh_flags) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_touch_oh(H5F_t *f, H5O_t *oh, hbool_t force)
{
H5O_chunk_proxy_t *chk_proxy = NULL;
hbool_t chk_dirtied = FALSE;
time_t now;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(f);
HDassert(oh);
if(oh->flags & H5O_HDR_STORE_TIMES) {
now = H5_now();
if(oh->version == H5O_VERSION_1) {
size_t idx;
for(idx = 0; idx < oh->nmesgs; idx++)
if(H5O_MSG_MTIME == oh->mesg[idx].type || H5O_MSG_MTIME_NEW == oh->mesg[idx].type)
break;
if(idx == oh->nmesgs) {
unsigned mesg_flags = 0;
if(!force)
HGOTO_DONE(SUCCEED);
if(H5O__msg_alloc(f, oh, H5O_MSG_MTIME_NEW, &mesg_flags, &now, &idx) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for modification time message")
oh->mesg[idx].flags = (uint8_t)mesg_flags;
}
if(NULL == (chk_proxy = H5O__chunk_protect(f, oh, oh->mesg[idx].chunkno)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
if(NULL == oh->mesg[idx].native) {
if(NULL == (oh->mesg[idx].native = H5FL_MALLOC(time_t)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "memory allocation failed for modification time message")
}
*((time_t *)(oh->mesg[idx].native)) = now;
oh->mesg[idx].dirty = TRUE;
chk_dirtied = TRUE;
}
else {
oh->atime = oh->ctime = now;
if(H5AC_mark_entry_dirty(oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
}
}
done:
if(chk_proxy && H5O__chunk_unprotect(f, chk_proxy, chk_dirtied) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_touch(const H5O_loc_t *loc, hbool_t force)
{
H5O_t *oh = NULL;
unsigned oh_flags = H5AC__NO_FLAGS_SET;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
if(NULL == (oh = H5O_protect(loc, H5AC__NO_FLAGS_SET, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
if(H5O_touch_oh(loc->file, oh, force) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to update object modificaton time")
oh_flags |= H5AC__DIRTIED_FLAG;
done:
if(oh && H5O_unprotect(loc, oh, oh_flags) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
}
#ifdef H5O_ENABLE_BOGUS
herr_t
H5O_bogus_oh(H5F_t *f, H5O_t *oh, unsigned bogus_id, unsigned mesg_flags)
{
size_t idx;
H5O_msg_class_t *type;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(oh);
for(idx = 0; idx < oh->nmesgs; idx++)
if(H5O_MSG_BOGUS_VALID == oh->mesg[idx].type || H5O_MSG_BOGUS_INVALID == oh->mesg[idx].type)
break;
if(idx == oh->nmesgs) {
H5O_bogus_t *bogus;
if(NULL == (bogus = H5MM_malloc(sizeof(H5O_bogus_t))))
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "memory allocation failed for 'bogus' message")
bogus->u = H5O_BOGUS_VALUE;
if(bogus_id == H5O_BOGUS_VALID_ID)
type = H5O_MSG_BOGUS_VALID;
else if(bogus_id == H5O_BOGUS_INVALID_ID)
type = H5O_MSG_BOGUS_INVALID;
else
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID for 'bogus' message")
if(H5O__msg_alloc(f, oh, type, &mesg_flags, bogus, &idx) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for 'bogus' message")
oh->mesg[idx].native = bogus;
oh->mesg[idx].flags = mesg_flags;
oh->mesg[idx].dirty = TRUE;
oh->cache_info.is_dirty = TRUE;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
herr_t
H5O_delete(H5F_t *f, haddr_t addr)
{
H5O_t *oh = NULL;
H5O_loc_t loc;
unsigned oh_flags = H5AC__NO_FLAGS_SET;
hbool_t corked;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_TAG(addr, FAIL)
HDassert(f);
HDassert(H5F_addr_defined(addr));
loc.file = f;
loc.addr = addr;
loc.holding_file = FALSE;
if(NULL == (oh = H5O_protect(&loc, H5AC__NO_FLAGS_SET, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
if(H5O__delete_oh(f, oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
if(H5AC_cork(f, addr, H5AC__GET_CORKED, &corked) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve an object's cork status")
if(corked)
if(H5AC_cork(f, addr, H5AC__UNCORK, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNCORK, FAIL, "unable to uncork an object")
oh_flags = H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
done:
if(oh && H5O_unprotect(&loc, oh, oh_flags) < 0)
HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static herr_t
H5O__delete_oh(H5F_t *f, H5O_t *oh)
{
H5O_mesg_t *curr_msg;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(f);
HDassert(oh);
for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
if(H5O__delete_mesg(f, oh, curr_msg) < 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_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type)
{
H5O_t *oh = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_TAG(loc->addr, FAIL)
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
if(H5O__obj_type_real(oh, obj_type) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
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)
}
static herr_t
H5O__obj_type_real(const H5O_t *oh, H5O_type_t *obj_type)
{
const H5O_obj_class_t *obj_class;
FUNC_ENTER_STATIC_NOERR
HDassert(oh);
HDassert(obj_type);
if(NULL == (obj_class = H5O__obj_class_real(oh))) {
H5E_clear_stack(NULL);
*obj_type = H5O_TYPE_UNKNOWN;
}
else
*obj_type = obj_class->type;
FUNC_LEAVE_NOAPI(SUCCEED)
}
const H5O_obj_class_t *
H5O__obj_class(const H5O_loc_t *loc)
{
H5O_t *oh = NULL;
const H5O_obj_class_t *ret_value = NULL;
FUNC_ENTER_PACKAGE_TAG(loc->addr)
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header")
if(NULL == (ret_value = H5O__obj_class_real(oh)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine object type")
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)
}
static const H5O_obj_class_t *
H5O__obj_class_real(const H5O_t *oh)
{
size_t i;
const H5O_obj_class_t *ret_value = NULL;
FUNC_ENTER_STATIC
HDassert(oh);
for(i = NELMTS(H5O_obj_class_g); i > 0; --i) {
htri_t isa;
if((isa = (H5O_obj_class_g[i - 1]->isa)(oh)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to determine object type")
else if(isa)
HGOTO_DONE(H5O_obj_class_g[i - 1])
}
if(0 == i)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to determine object type")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5O_loc_t *
H5O_get_loc(hid_t object_id)
{
H5O_loc_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
switch(H5I_get_type(object_id)) {
case H5I_GROUP:
if(NULL == (ret_value = H5O_OBJ_GROUP->get_oloc(object_id)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get object location from group ID")
break;
case H5I_DATASET:
if(NULL == (ret_value = H5O_OBJ_DATASET->get_oloc(object_id)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get object location from dataset ID")
break;
case H5I_DATATYPE:
if(NULL == (ret_value = H5O_OBJ_DATATYPE->get_oloc(object_id)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get object location from datatype ID")
break;
case H5I_UNINIT:
case H5I_BADID:
case H5I_FILE:
case H5I_DATASPACE:
case H5I_ATTR:
case H5I_REFERENCE:
case H5I_VFL:
case H5I_GENPROP_CLS:
case H5I_GENPROP_LST:
case H5I_ERROR_CLASS:
case H5I_ERROR_MSG:
case H5I_ERROR_STACK:
case H5I_NTYPES:
default:
HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, NULL, "invalid object type")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_loc_reset(H5O_loc_t *loc)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(loc);
HDmemset(loc, 0, sizeof(H5O_loc_t));
loc->addr = HADDR_UNDEF;
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5O_loc_copy(H5O_loc_t *dst, H5O_loc_t *src, H5_copy_depth_t depth)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(src);
HDassert(dst);
HDassert(depth == H5_COPY_SHALLOW || depth == H5_COPY_DEEP);
if(depth == H5_COPY_SHALLOW)
H5O_loc_copy_shallow(dst, src);
else
H5O_loc_copy_deep(dst, src);
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5O_loc_copy_shallow(H5O_loc_t *dst, H5O_loc_t *src)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(src);
HDassert(dst);
H5MM_memcpy(dst, src, sizeof(H5O_loc_t));
H5O_loc_reset(src);
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5O_loc_copy_deep(H5O_loc_t *dst, const H5O_loc_t *src)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(src);
HDassert(dst);
H5MM_memcpy(dst, src, sizeof(H5O_loc_t));
if(src->holding_file)
H5F_INCR_NOPEN_OBJS(dst->file);
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5O_loc_hold_file(H5O_loc_t *loc)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(loc);
HDassert(loc->file);
if(!loc->holding_file) {
H5F_INCR_NOPEN_OBJS(loc->file);
loc->holding_file = TRUE;
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5O_loc_free(H5O_loc_t *loc)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(loc);
if(loc->holding_file) {
H5F_DECR_NOPEN_OBJS(loc->file);
loc->holding_file = FALSE;
if(H5F_NOPEN_OBJS(loc->file) <= 0) {
if(H5F_try_close(loc->file, NULL) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file")
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_get_hdr_info(const H5O_loc_t *loc, H5O_hdr_info_t *hdr)
{
H5O_t *oh = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
HDassert(hdr);
HDmemset(hdr, 0, sizeof(*hdr));
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
if(H5O__get_hdr_info_real(oh, hdr) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object header info")
done:
if(oh && H5O_unprotect(loc, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5O__get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr)
{
const H5O_mesg_t *curr_msg;
const H5O_chunk_t *curr_chunk;
unsigned u;
FUNC_ENTER_STATIC_NOERR
HDassert(oh);
HDassert(hdr);
hdr->version = oh->version;
H5_CHECKED_ASSIGN(hdr->nmesgs, unsigned, oh->nmesgs, size_t);
H5_CHECKED_ASSIGN(hdr->nchunks, unsigned, oh->nchunks, size_t);
hdr->flags = oh->flags;
hdr->space.meta = (hsize_t)H5O_SIZEOF_HDR(oh) + (hsize_t)(H5O_SIZEOF_CHKHDR_OH(oh) * (oh->nchunks - 1));
hdr->space.mesg = 0;
hdr->space.free = 0;
hdr->mesg.present = 0;
hdr->mesg.shared = 0;
for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
uint64_t type_flag;
if(H5O_NULL_ID == curr_msg->type->id)
hdr->space.free += (hsize_t)((size_t)H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size);
else if(H5O_CONT_ID == curr_msg->type->id)
hdr->space.meta += (hsize_t)((size_t)H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size);
else {
hdr->space.meta += (hsize_t)H5O_SIZEOF_MSGHDR_OH(oh);
hdr->space.mesg += curr_msg->raw_size;
}
type_flag = ((uint64_t)1) << curr_msg->type->id;
hdr->mesg.present |= type_flag;
if(curr_msg->flags & H5O_MSG_FLAG_SHARED) \
hdr->mesg.shared |= type_flag;
}
hdr->space.total = 0;
for(u = 0, curr_chunk = &oh->chunk[0]; u < oh->nchunks; u++, curr_chunk++) {
hdr->space.total += curr_chunk->size;
hdr->space.free += curr_chunk->gap;
}
HDassert(hdr->space.total == (hdr->space.free + hdr->space.meta + hdr->space.mesg));
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5O_get_info(const H5O_loc_t *loc, H5O_info_t *oinfo, unsigned fields)
{
const H5O_obj_class_t *obj_class;
H5O_t *oh = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_TAG(loc->addr, FAIL)
HDassert(loc);
HDassert(oinfo);
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
if(NULL == (obj_class = H5O__obj_class_real(oh)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to determine object class")
HDmemset(oinfo, 0, sizeof(*oinfo));
if(fields & H5O_INFO_BASIC) {
H5F_GET_FILENO(loc->file, oinfo->fileno);
oinfo->addr = loc->addr;
oinfo->type = obj_class->type;
oinfo->rc = oh->nlink;
}
if(fields & H5O_INFO_TIME) {
if(oh->version > H5O_VERSION_1) {
oinfo->atime = oh->atime;
oinfo->mtime = oh->mtime;
oinfo->ctime = oh->ctime;
oinfo->btime = oh->btime;
}
else {
htri_t exists;
oinfo->atime = 0;
oinfo->mtime = 0;
oinfo->btime = 0;
if((exists = H5O_msg_exists_oh(oh, H5O_MTIME_ID)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "unable to check for MTIME message")
if(exists > 0) {
if(NULL == H5O_msg_read_oh(loc->file, oh, H5O_MTIME_ID, &oinfo->ctime))
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read MTIME message")
}
else {
if((exists = H5O_msg_exists_oh(oh, H5O_MTIME_NEW_ID)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "unable to check for MTIME_NEW message")
if(exists > 0) {
if(NULL == H5O_msg_read_oh(loc->file, oh, H5O_MTIME_NEW_ID, &oinfo->ctime))
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read MTIME_NEW message")
}
else
oinfo->ctime = 0;
}
}
}
if(fields & H5O_INFO_HDR)
if(H5O__get_hdr_info_real(oh, &oinfo->hdr) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object header info")
if(fields & H5O_INFO_NUM_ATTRS)
if(H5O_attr_count_real(loc->file, oh, &oinfo->num_attrs) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve attribute count")
if(fields & H5O_INFO_META_SIZE) {
if(obj_class->bh_info)
if((obj_class->bh_info)(loc, oh, &oinfo->meta_size.obj) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object's btree & heap info")
if(!(fields & H5O_INFO_NUM_ATTRS) || oinfo->num_attrs > 0) {
if(H5O__attr_bh_info(loc->file, oh, &oinfo->meta_size.attr) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve attribute btree & heap info")
}
}
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)
}
herr_t
H5O__get_info_by_idx(const H5G_loc_t *loc, const char *group_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, H5O_info_t *oinfo, unsigned fields)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(loc);
HDassert(group_name && *group_name);
HDassert(oinfo);
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find_by_idx(loc, group_name, idx_type, order, n, &obj_loc) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
loc_found = TRUE;
if(H5O_get_info(obj_loc.oloc, oinfo, fields) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object info")
done:
if(loc_found && H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_get_create_plist(const H5O_loc_t *loc, H5P_genplist_t *oc_plist)
{
H5O_t *oh = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
HDassert(oc_plist);
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
if(oh->version > H5O_VERSION_1) {
uint8_t ohdr_flags;
if(H5P_set(oc_plist, H5O_CRT_ATTR_MAX_COMPACT_NAME, &oh->max_compact) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set max. # of compact attributes in property list")
if(H5P_set(oc_plist, H5O_CRT_ATTR_MIN_DENSE_NAME, &oh->min_dense) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set min. # of dense attributes in property list")
H5_CHECKED_ASSIGN(ohdr_flags, uint8_t, oh->flags & (H5O_HDR_ATTR_CRT_ORDER_TRACKED | H5O_HDR_ATTR_CRT_ORDER_INDEXED | H5O_HDR_STORE_TIMES), int);
if(H5P_set(oc_plist, H5O_CRT_OHDR_FLAGS_NAME, &ohdr_flags) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set object header 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)
}
herr_t
H5O_get_nlinks(const H5O_loc_t *loc, hsize_t *nlinks)
{
H5O_t *oh = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
HDassert(nlinks);
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
*nlinks = oh->link_msgs_seen;
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)
}
void *
H5O_obj_create(H5F_t *f, H5O_type_t obj_type, void *crt_info, H5G_loc_t *obj_loc)
{
size_t u;
void *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(f);
HDassert(obj_type >= H5O_TYPE_GROUP && obj_type <= H5O_TYPE_NAMED_DATATYPE);
HDassert(crt_info);
HDassert(obj_loc);
for(u = 0; u < NELMTS(H5O_obj_class_g); u++) {
if(H5O_obj_class_g[u]->type == obj_type) {
HDassert(H5O_obj_class_g[u]->create);
if(NULL == (ret_value = H5O_obj_class_g[u]->create(f, crt_info, obj_loc)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object")
break;
}
}
HDassert(ret_value);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
haddr_t
H5O_get_oh_addr(const H5O_t *oh)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(oh);
HDassert(oh->chunk);
FUNC_LEAVE_NOAPI(oh->chunk[0].addr)
}
uint8_t
H5O_get_oh_flags(const H5O_t *oh)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(oh);
FUNC_LEAVE_NOAPI(oh->flags);
}
time_t
H5O_get_oh_mtime(const H5O_t *oh)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(oh);
HDassert(oh->mtime);
FUNC_LEAVE_NOAPI(oh->mtime);
}
uint8_t
H5O_get_oh_version(const H5O_t *oh)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(oh);
HDassert(oh->version);
FUNC_LEAVE_NOAPI(oh->version);
}
herr_t
H5O_get_rc_and_type(const H5O_loc_t *loc, unsigned *rc, H5O_type_t *otype)
{
H5O_t *oh = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
if(rc)
*rc = oh->nlink;
if(otype)
if(H5O__obj_type_real(oh, otype) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
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)
}
static herr_t
H5O__free_visit_visited(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *operator_data)
{
FUNC_ENTER_STATIC_NOERR
item = H5FL_FREE(H5_obj_t, item);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5O__visit_cb(hid_t H5_ATTR_UNUSED group, const char *name, const H5L_info_t *linfo,
void *_udata)
{
H5O_iter_visit_ud_t *udata = (H5O_iter_visit_ud_t *)_udata;
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t obj_found = FALSE;
herr_t ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC
HDassert(name);
HDassert(linfo);
HDassert(udata);
if(linfo->type == H5L_TYPE_HARD) {
H5_obj_t obj_pos;
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find(udata->start_loc, name, &obj_loc) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5_ITER_ERROR, "object not found")
obj_found = TRUE;
H5F_GET_FILENO(obj_oloc.file, obj_pos.fileno);
obj_pos.addr = obj_oloc.addr;
if(NULL == H5SL_search(udata->visited, &obj_pos)) {
H5O_info_t oinfo;
if(H5O_get_info(&obj_oloc, &oinfo, udata->fields) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info")
ret_value = (udata->op)(udata->obj_id, name, &oinfo, udata->op_data);
if(ret_value == H5_ITER_CONT) {
if(oinfo.rc > 1) {
H5_obj_t *new_node;
if((new_node = H5FL_MALLOC(H5_obj_t)) == NULL)
HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate object node")
*new_node = obj_pos;
if(H5SL_insert(udata->visited, new_node, new_node) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert object node into visited list")
}
}
}
}
done:
if(obj_found && H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O__visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
H5_iter_order_t order, H5O_iterate_t op, void *op_data, unsigned fields)
{
H5O_iter_visit_ud_t udata;
H5G_loc_t loc;
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
H5O_info_t oinfo;
hid_t obj_id = H5I_INVALID_HID;
herr_t ret_value = FAIL;
FUNC_ENTER_PACKAGE
HDmemset(&udata, 0, sizeof(udata));
if(H5G_loc(loc_id, &loc) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find(&loc, obj_name, &obj_loc) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
loc_found = TRUE;
if(H5O_get_info(&obj_oloc, &oinfo, fields) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object info")
if((obj_id = H5O__open_by_loc(&obj_loc, TRUE)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
if((ret_value = op(obj_id, ".", &oinfo, op_data)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "can't visit objects")
if(ret_value != H5_ITER_CONT)
HGOTO_DONE(ret_value);
if(oinfo.type == H5O_TYPE_GROUP) {
H5G_loc_t start_loc;
if(H5G_loc(obj_id, &start_loc) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
udata.obj_id = obj_id;
udata.start_loc = &start_loc;
udata.op = op;
udata.op_data = op_data;
udata.fields = fields;
if((udata.visited = H5SL_create(H5SL_TYPE_OBJ, NULL)) == NULL)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects")
if(oinfo.rc > 1) {
H5_obj_t *obj_pos;
if((obj_pos = H5FL_MALLOC(H5_obj_t)) == NULL)
HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "can't allocate object node")
obj_pos->fileno = oinfo.fileno;
obj_pos->addr = oinfo.addr;
if(H5SL_insert(udata.visited, obj_pos, obj_pos) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object node into visited list")
}
if((ret_value = H5G_visit(obj_id, ".", idx_type, order, H5O__visit_cb, &udata)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
}
done:
if(obj_id > 0) {
if(H5I_dec_app_ref(obj_id) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object")
}
else if(loc_found && H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
if(udata.visited)
H5SL_destroy(udata.visited, H5O__free_visit_visited, NULL);
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O__inc_rc(H5O_t *oh)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(oh);
if(oh->rc == 0)
if(H5AC_pin_protected_entry(oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
oh->rc++;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O__dec_rc(H5O_t *oh)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(oh);
oh->rc--;
if(oh->rc == 0)
if(H5AC_unpin_entry(oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5O_dec_rc_by_loc(const H5O_loc_t *loc)
{
H5O_t *oh = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(loc);
if(NULL == (oh = H5O_protect(loc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
if(H5O__dec_rc(oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement reference count on object header")
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)
}
H5AC_proxy_entry_t *
H5O_get_proxy(const H5O_t *oh)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(oh);
FUNC_LEAVE_NOAPI(oh->proxy)
}
herr_t
H5O__free(H5O_t *oh)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(oh);
HDassert(0 == oh->rc);
if(oh->chunk) {
for(u = 0; u < oh->nchunks; u++)
oh->chunk[u].image = H5FL_BLK_FREE(chunk_image, oh->chunk[u].image);
oh->chunk = (H5O_chunk_t *)H5FL_SEQ_FREE(H5O_chunk_t, oh->chunk);
}
if(oh->mesg) {
for(u = 0; u < oh->nmesgs; u++) {
#ifndef NDEBUG
if(oh->ndecode_dirtied && oh->mesg[u].dirty)
oh->ndecode_dirtied--;
else
HDassert(oh->mesg[u].dirty == 0);
#endif
H5O__msg_free_mesg(&oh->mesg[u]);
}
HDassert(!oh->ndecode_dirtied);
oh->mesg = (H5O_mesg_t *)H5FL_SEQ_FREE(H5O_mesg_t, oh->mesg);
}
if(oh->proxy)
if(H5AC_proxy_entry_dest(oh->proxy) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy virtual entry used for proxy")
oh = H5FL_FREE(H5O_t, oh);
done:
FUNC_LEAVE_NOAPI(ret_value)
}