#define H5O_FRIEND
#include "H5SMmodule.h"
#include "H5private.h"
#include "H5Eprivate.h"
#include "H5Fprivate.h"
#include "H5FLprivate.h"
#include "H5MFprivate.h"
#include "H5MMprivate.h"
#include "H5Opkg.h"
#include "H5SMpkg.h"
typedef struct H5SM_read_udata_t {
H5F_t *file;
H5O_msg_crt_idx_t idx;
size_t buf_size;
void *encoding_buf;
} H5SM_read_udata_t;
static herr_t H5SM__create_index(H5F_t *f, H5SM_index_header_t *header);
static herr_t H5SM__delete_index(H5F_t *f, H5SM_index_header_t *header,
hbool_t delete_heap);
static haddr_t H5SM__create_list(H5F_t *f, H5SM_index_header_t *header);
static herr_t H5SM__find_in_list(const H5SM_list_t *list, const H5SM_mesg_key_t *key,
size_t *empty_pos, size_t *list_pos);
static herr_t H5SM__convert_list_to_btree(H5F_t * f, H5SM_index_header_t * header,
H5SM_list_t **_list, H5HF_t *fheap, H5O_t *open_oh);
static herr_t H5SM__convert_btree_to_list(H5F_t * f, H5SM_index_header_t * header);
static herr_t H5SM__incr_ref(void *record, void *_op_data, hbool_t *changed);
static herr_t H5SM__write_mesg(H5F_t *f, H5O_t *open_oh, H5SM_index_header_t *header,
hbool_t defer, unsigned type_id, void *mesg, unsigned *cache_flags_ptr);
static herr_t H5SM__decr_ref(void *record, void *op_data, hbool_t *changed);
static herr_t H5SM__delete_from_index(H5F_t *f, H5O_t *open_oh, H5SM_index_header_t *header,
const H5O_shared_t * mesg, unsigned *cache_flags, size_t * mesg_size,
void ** encoded_mesg);
static herr_t H5SM__type_to_flag(unsigned type_id, unsigned *type_flag);
static herr_t H5SM__read_iter_op(H5O_t *oh, H5O_mesg_t *mesg, unsigned sequence,
unsigned *oh_modified, void *_udata);
static herr_t H5SM__read_mesg_fh_cb(const void *obj, size_t obj_len, void *_udata);
static herr_t H5SM__read_mesg(H5F_t *f, const H5SM_sohm_t *mesg, H5HF_t *fheap,
H5O_t * open_oh, size_t *encoding_size , void ** encoded_mesg );
hbool_t H5_PKG_INIT_VAR = FALSE;
H5FL_DEFINE(H5SM_master_table_t);
H5FL_ARR_DEFINE(H5SM_index_header_t, H5O_SHMESG_MAX_NINDEXES);
H5FL_DEFINE(H5SM_list_t);
H5FL_ARR_DEFINE(H5SM_sohm_t, H5O_SHMESG_MAX_LIST_SIZE);
herr_t
H5SM_init(H5F_t *f, H5P_genplist_t * fc_plist, const H5O_loc_t *ext_loc)
{
H5O_shmesg_table_t sohm_table;
H5SM_master_table_t *table = NULL;
H5AC_ring_t orig_ring = H5AC_RING_INV;
haddr_t table_addr = HADDR_UNDEF;
unsigned list_max, btree_min;
unsigned index_type_flags[H5O_SHMESG_MAX_NINDEXES];
unsigned minsizes[H5O_SHMESG_MAX_NINDEXES];
unsigned type_flags_used;
unsigned x;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_TAG(H5AC__SOHM_TAG, FAIL)
HDassert(f);
HDassert(!H5F_addr_defined(H5F_SOHM_ADDR(f)));
H5AC_set_ring(H5AC_RING_USER, &orig_ring);
if(NULL == (table = H5FL_CALLOC(H5SM_master_table_t)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTALLOC, FAIL, "memory allocation failed for SOHM table")
table->num_indexes = H5F_SOHM_NINDEXES(f);
table->table_size = H5SM_TABLE_SIZE(f);
if(H5P_get(fc_plist, H5F_CRT_SHMSG_INDEX_TYPES_NAME, &index_type_flags) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't get SOHM type flags")
if(H5P_get(fc_plist, H5F_CRT_SHMSG_LIST_MAX_NAME, &list_max) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't get SOHM list maximum")
if(H5P_get(fc_plist, H5F_CRT_SHMSG_BTREE_MIN_NAME, &btree_min) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't get SOHM btree minimum")
if(H5P_get(fc_plist, H5F_CRT_SHMSG_INDEX_MINSIZE_NAME, &minsizes) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't get SOHM message min sizes")
if(table->num_indexes > H5O_SHMESG_MAX_NINDEXES)
HGOTO_ERROR(H5E_SOHM, H5E_BADRANGE, FAIL, "number of indexes in property list is too large")
type_flags_used = 0;
for(x = 0; x < table->num_indexes; ++x) {
if(index_type_flags[x] & type_flags_used)
HGOTO_ERROR(H5E_SOHM, H5E_BADVALUE, FAIL, "the same shared message type flag is assigned to more than one index")
type_flags_used |= index_type_flags[x];
}
HDassert(table->num_indexes < 256);
HDassert(list_max + 1 >= btree_min);
HDassert(table->num_indexes > 0 && table->num_indexes <= H5O_SHMESG_MAX_NINDEXES);
if(NULL == (table->indexes = (H5SM_index_header_t *)H5FL_ARR_MALLOC(H5SM_index_header_t, (size_t)table->num_indexes)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "memory allocation failed for SOHM indexes")
for(x = 0; x < table->num_indexes; x++) {
table->indexes[x].btree_min = btree_min;
table->indexes[x].list_max = list_max;
table->indexes[x].mesg_types = index_type_flags[x];
table->indexes[x].min_mesg_size = minsizes[x];
table->indexes[x].index_addr = HADDR_UNDEF;
table->indexes[x].heap_addr = HADDR_UNDEF;
table->indexes[x].num_messages = 0;
if(table->indexes[x].list_max > 0)
table->indexes[x].index_type = H5SM_LIST;
else
table->indexes[x].index_type = H5SM_BTREE;
table->indexes[x].list_size = H5SM_LIST_SIZE(f, list_max);
}
if(HADDR_UNDEF == (table_addr = H5MF_alloc(f, H5FD_MEM_SOHM_TABLE, (hsize_t)table->table_size)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "file allocation failed for SOHM table")
if(H5AC_insert_entry(f, H5AC_SOHM_TABLE, table_addr, table, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINS, FAIL, "can't add SOHM table to cache")
H5F_SET_SOHM_ADDR(f, table_addr);
if(type_flags_used & H5O_SHMESG_ATTR_FLAG)
H5F_SET_STORE_MSG_CRT_IDX(f, TRUE);
H5AC_set_ring(H5AC_RING_SBE, NULL);
sohm_table.addr = H5F_SOHM_ADDR(f);
sohm_table.version = H5F_SOHM_VERS(f);
sohm_table.nindexes = H5F_SOHM_NINDEXES(f);
if(H5O_msg_create(ext_loc, H5O_SHMESG_ID, H5O_MSG_FLAG_CONSTANT | H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &sohm_table) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINIT, FAIL, "unable to update SOHM header message")
done:
if(orig_ring != H5AC_RING_INV)
H5AC_set_ring(orig_ring, NULL);
if(ret_value < 0) {
if(table_addr != HADDR_UNDEF)
H5MF_xfree(f, H5FD_MEM_SOHM_TABLE, table_addr, (hsize_t)table->table_size);
if(table != NULL)
table = H5FL_FREE(H5SM_master_table_t, table);
}
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static herr_t
H5SM__type_to_flag(unsigned type_id, unsigned *type_flag)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
switch(type_id) {
case H5O_FILL_ID:
type_id = H5O_FILL_NEW_ID;
H5_ATTR_FALLTHROUGH
case H5O_SDSPACE_ID:
case H5O_DTYPE_ID:
case H5O_FILL_NEW_ID:
case H5O_PLINE_ID:
case H5O_ATTR_ID:
*type_flag = (unsigned)1 << type_id;
break;
default:
HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "unknown message type ID")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
ssize_t
H5SM_get_index(const H5SM_master_table_t *table, unsigned type_id)
{
size_t x;
unsigned type_flag;
ssize_t ret_value = FAIL;
FUNC_ENTER_NOAPI_NOINIT
if(H5SM__type_to_flag(type_id, &type_flag) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't map message type to flag")
for(x = 0; x < table->num_indexes; ++x)
if(table->indexes[x].mesg_types & type_flag)
HGOTO_DONE((ssize_t)x)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5SM_type_shared(H5F_t *f, unsigned type_id)
{
H5SM_master_table_t *table = NULL;
unsigned type_flag;
size_t u;
htri_t ret_value = FALSE;
FUNC_ENTER_NOAPI_NOINIT_TAG(H5AC__SOHM_TAG)
if(H5SM__type_to_flag(type_id, &type_flag) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't map message type to flag")
if(H5F_addr_defined(H5F_SOHM_ADDR(f))) {
H5SM_table_cache_ud_t cache_udata;
cache_udata.f = f;
if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
}
else
HGOTO_DONE(FALSE)
for(u = 0; u < table->num_indexes; u++)
if(table->indexes[u].mesg_types & type_flag)
HGOTO_DONE(TRUE)
done:
if(table && H5AC_unprotect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5SM_get_fheap_addr(H5F_t *f, unsigned type_id, haddr_t *fheap_addr)
{
H5SM_master_table_t *table = NULL;
H5SM_table_cache_ud_t cache_udata;
ssize_t index_num;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_TAG(H5AC__SOHM_TAG, FAIL)
HDassert(f);
HDassert(fheap_addr);
cache_udata.f = f;
if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
if((index_num = H5SM_get_index(table, type_id)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to find correct SOHM index")
*fheap_addr = table->indexes[index_num].heap_addr;
done:
if(table && H5AC_unprotect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static herr_t
H5SM__create_index(H5F_t *f, H5SM_index_header_t *header)
{
H5HF_create_t fheap_cparam;
H5HF_t *fheap = NULL;
H5B2_t *bt2 = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(header);
HDassert(header->index_addr == HADDR_UNDEF);
HDassert(header->btree_min <= header->list_max + 1);
if(header->list_max > 0) {
haddr_t list_addr = HADDR_UNDEF;
if(HADDR_UNDEF == (list_addr = H5SM__create_list(f, header)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTCREATE, FAIL, "list creation failed for SOHM index")
header->index_type = H5SM_LIST;
header->index_addr = list_addr;
}
else {
H5B2_create_t bt2_cparam;
haddr_t tree_addr = HADDR_UNDEF;
bt2_cparam.cls = H5SM_INDEX;
bt2_cparam.node_size = (uint32_t)H5SM_B2_NODE_SIZE;
bt2_cparam.rrec_size = (uint32_t)H5SM_SOHM_ENTRY_SIZE(f);
bt2_cparam.split_percent = H5SM_B2_SPLIT_PERCENT;
bt2_cparam.merge_percent = H5SM_B2_MERGE_PERCENT;
if(NULL == (bt2 = H5B2_create(f, &bt2_cparam, f)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTCREATE, FAIL, "B-tree creation failed for SOHM index")
if(H5B2_get_addr(bt2, &tree_addr) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't get v2 B-tree address for SOHM index")
header->index_type = H5SM_BTREE;
header->index_addr = tree_addr;
}
HDmemset(&fheap_cparam, 0, sizeof(fheap_cparam));
fheap_cparam.managed.width = H5O_FHEAP_MAN_WIDTH;
fheap_cparam.managed.start_block_size = H5O_FHEAP_MAN_START_BLOCK_SIZE;
fheap_cparam.managed.max_direct_size = H5O_FHEAP_MAN_MAX_DIRECT_SIZE;
fheap_cparam.managed.max_index = H5O_FHEAP_MAN_MAX_INDEX;
fheap_cparam.managed.start_root_rows = H5O_FHEAP_MAN_START_ROOT_ROWS;
fheap_cparam.checksum_dblocks = H5O_FHEAP_CHECKSUM_DBLOCKS;
fheap_cparam.id_len = 0;
fheap_cparam.max_man_size = H5O_FHEAP_MAX_MAN_SIZE;
if(NULL == (fheap = H5HF_create(f, &fheap_cparam)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTINIT, FAIL, "unable to create fractal heap")
if(H5HF_get_heap_addr(fheap, &(header->heap_addr)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGETSIZE, FAIL, "can't get fractal heap address")
#ifndef NDEBUG
{
size_t fheap_id_len;
if(H5HF_get_id_len(fheap, &fheap_id_len) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGETSIZE, FAIL, "can't get fractal heap ID length")
HDassert(fheap_id_len == H5O_FHEAP_ID_LEN);
}
#endif
done:
if(fheap && H5HF_close(fheap) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close fractal heap")
if(bt2 && H5B2_close(bt2) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for SOHM index")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5SM__delete_index(H5F_t *f, H5SM_index_header_t *header, hbool_t delete_heap)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
if(header->index_type == H5SM_LIST) {
unsigned index_status = 0;
if(H5AC_get_entry_status(f, header->index_addr, &index_status) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "unable to check metadata cache status for direct block")
if(index_status & H5AC_ES__IN_CACHE) {
HDassert(!(index_status & H5AC_ES__IS_PINNED));
HDassert(!(index_status & H5AC_ES__IS_PROTECTED));
if(H5AC_expunge_entry(f, H5AC_SOHM_LIST, header->index_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTREMOVE, FAIL, "unable to remove list index from cache")
}
}
else {
HDassert(header->index_type == H5SM_BTREE);
if(H5B2_delete(f, header->index_addr, f, NULL, NULL) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete B-tree")
if(header->btree_min > 0)
header->index_type = H5SM_LIST;
}
if(delete_heap == TRUE) {
if(H5HF_delete(f, header->heap_addr) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete fractal heap")
header->heap_addr = HADDR_UNDEF;
}
header->index_addr = HADDR_UNDEF;
header->num_messages = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static haddr_t
H5SM__create_list(H5F_t *f, H5SM_index_header_t *header)
{
H5SM_list_t *list = NULL;
hsize_t x;
size_t num_entries;
haddr_t addr = HADDR_UNDEF;
haddr_t ret_value = HADDR_UNDEF;
FUNC_ENTER_STATIC_TAG(H5AC__SOHM_TAG)
HDassert(f);
HDassert(header);
num_entries = header->list_max;
if(NULL == (list = H5FL_CALLOC(H5SM_list_t)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed for SOHM list")
if(NULL == (list->messages = (H5SM_sohm_t *)H5FL_ARR_CALLOC(H5SM_sohm_t, num_entries)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed for SOHM list")
for(x = 0; x < num_entries; x++)
list->messages[x].location = H5SM_NO_LOC;
list->header = header;
if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_SOHM_INDEX, (hsize_t)header->list_size)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed for SOHM list")
if(H5AC_insert_entry(f, H5AC_SOHM_LIST, addr, list, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINS, HADDR_UNDEF, "can't add SOHM list to cache")
ret_value = addr;
done:
if(ret_value == HADDR_UNDEF) {
if(list != NULL) {
if(list->messages != NULL)
list->messages = H5FL_ARR_FREE(H5SM_sohm_t, list->messages);
list = H5FL_FREE(H5SM_list_t, list);
}
if(addr != HADDR_UNDEF)
H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, addr, (hsize_t)header->list_size);
}
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static herr_t
H5SM__convert_list_to_btree(H5F_t *f, H5SM_index_header_t *header,
H5SM_list_t **_list, H5HF_t *fheap, H5O_t *open_oh)
{
H5SM_list_t *list;
H5SM_mesg_key_t key;
H5B2_create_t bt2_cparam;
H5B2_t *bt2 = NULL;
haddr_t tree_addr;
size_t num_messages;
size_t x;
void * encoding_buf = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(_list && *_list);
HDassert(header);
list = *_list;
bt2_cparam.cls = H5SM_INDEX;
bt2_cparam.node_size = (uint32_t)H5SM_B2_NODE_SIZE;
bt2_cparam.rrec_size = (uint32_t)H5SM_SOHM_ENTRY_SIZE(f);
bt2_cparam.split_percent = H5SM_B2_SPLIT_PERCENT;
bt2_cparam.merge_percent = H5SM_B2_MERGE_PERCENT;
if(NULL == (bt2 = H5B2_create(f, &bt2_cparam, f)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTCREATE, FAIL, "B-tree creation failed for SOHM index")
if(H5B2_get_addr(bt2, &tree_addr) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't get v2 B-tree address for SOHM index")
key.file = f;
key.fheap = fheap;
key.encoding_size = 0;
key.encoding = NULL;
for(x = 0; x < header->list_max; x++) {
if(list->messages[x].location != H5SM_NO_LOC) {
key.message = list->messages[x];
if(H5SM__read_mesg(f, &(key.message), fheap, open_oh, &key.encoding_size, &encoding_buf) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, FAIL, "Couldn't read SOHM message in list")
key.encoding = encoding_buf;
if(H5B2_insert(bt2, &key) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "couldn't add SOHM to B-tree")
if(encoding_buf)
encoding_buf = H5MM_xfree(encoding_buf);
}
}
if(H5AC_unprotect(f, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to release SOHM list")
*_list = list = NULL;
num_messages = header->num_messages;
if(H5SM__delete_index(f, header, FALSE) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "can't free list index")
header->index_addr = tree_addr;
header->index_type = H5SM_BTREE;
header->num_messages = num_messages;
done:
if(bt2 && H5B2_close(bt2) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for SOHM index")
if(encoding_buf)
encoding_buf = H5MM_xfree(encoding_buf);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5SM__convert_btree_to_list(H5F_t * f, H5SM_index_header_t * header)
{
H5SM_list_t *list = NULL;
H5SM_list_cache_ud_t cache_udata;
haddr_t btree_addr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_TAG(H5AC__SOHM_TAG)
btree_addr = header->index_addr;
header->num_messages = 0;
header->index_type = H5SM_LIST;
if(HADDR_UNDEF == (header->index_addr = H5SM__create_list(f, header)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTINIT, FAIL, "unable to create shared message list")
cache_udata.f = f;
cache_udata.header = header;
if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, H5AC_SOHM_LIST, header->index_addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM list index")
if(H5B2_delete(f, btree_addr, f, H5SM_bt2_convert_to_list_op, list) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete B-tree")
done:
if(list && H5AC_unprotect(f, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DIRTIED_FLAG) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to unprotect SOHM index")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static htri_t
H5SM_can_share_common(const H5F_t *f, unsigned type_id, const void *mesg)
{
htri_t ret_value = FAIL;
FUNC_ENTER_NOAPI_NOINIT
if(!H5F_addr_defined(H5F_SOHM_ADDR(f)))
HGOTO_DONE(FALSE)
if((ret_value = H5O_msg_can_share(type_id, mesg)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "can_share callback returned error")
if(ret_value == FALSE)
HGOTO_DONE(FALSE)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5SM_can_share(H5F_t *f, H5SM_master_table_t *table,
ssize_t *sohm_index_num, unsigned type_id, const void *mesg)
{
size_t mesg_size;
H5SM_master_table_t *my_table = NULL;
ssize_t index_num;
htri_t tri_ret;
htri_t ret_value = TRUE;
FUNC_ENTER_NOAPI_TAG(H5AC__SOHM_TAG, FAIL)
if((tri_ret = H5SM_can_share_common(f, type_id, mesg)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "'trivial' sharing checks returned error")
if(tri_ret == FALSE)
HGOTO_DONE(FALSE)
if(table)
my_table = table;
else {
H5SM_table_cache_ud_t cache_udata;
cache_udata.f = f;
if(NULL == (my_table = (H5SM_master_table_t *)H5AC_protect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
}
if((index_num = H5SM_get_index(my_table, type_id)) < 0) {
H5E_clear_stack(NULL);
HGOTO_DONE(FALSE)
}
if(0 == (mesg_size = H5O_msg_raw_size(f, type_id, TRUE, mesg)))
HGOTO_ERROR(H5E_SOHM, H5E_BADMESG, FAIL, "unable to get OH message size")
if(mesg_size < my_table->indexes[index_num].min_mesg_size)
HGOTO_DONE(FALSE)
if(sohm_index_num)
*sohm_index_num = index_num;
done:
if(my_table && my_table != table && H5AC_unprotect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), my_table, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
htri_t
H5SM_try_share(H5F_t *f, H5O_t *open_oh, unsigned defer_flags,
unsigned type_id, void *mesg, unsigned *mesg_flags)
{
H5SM_master_table_t *table = NULL;
H5SM_table_cache_ud_t cache_udata;
unsigned cache_flags = H5AC__NO_FLAGS_SET;
ssize_t index_num;
htri_t tri_ret;
#ifndef NDEBUG
unsigned deferred_type = -1u;
#endif
htri_t ret_value = TRUE;
FUNC_ENTER_NOAPI_TAG(H5AC__SOHM_TAG, FAIL)
if(defer_flags & H5SM_WAS_DEFERRED)
#ifndef NDEBUG
deferred_type = ((H5O_shared_t *)mesg)->type;
#else
if((((H5O_shared_t *)mesg)->type != H5O_SHARE_TYPE_HERE)
&& (((H5O_shared_t *)mesg)->type != H5O_SHARE_TYPE_SOHM))
HGOTO_DONE(FALSE);
#endif
if(mesg_flags && (*mesg_flags & H5O_MSG_FLAG_DONTSHARE))
HGOTO_DONE(FALSE)
if((tri_ret = H5SM_can_share_common(f, type_id, mesg)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "'trivial' sharing checks returned error")
if(tri_ret == FALSE)
HGOTO_DONE(FALSE)
cache_udata.f = f;
if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
if((tri_ret = H5SM_can_share(f, table, &index_num, type_id, mesg)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "'complex' sharing checks returned error")
if(tri_ret == FALSE)
HGOTO_DONE(FALSE)
if(table->indexes[index_num].index_addr == HADDR_UNDEF) {
if(H5SM__create_index(f, &(table->indexes[index_num])) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINIT, FAIL, "unable to create SOHM index")
cache_flags |= H5AC__DIRTIED_FLAG;
}
if(H5SM__write_mesg(f, open_oh, &(table->indexes[index_num]),
(defer_flags & H5SM_DEFER) != 0, type_id, mesg, &cache_flags) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "can't write shared message")
if(mesg_flags) {
if(((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE)
*mesg_flags |= H5O_MSG_FLAG_SHAREABLE;
else {
HDassert(((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_SOHM);
*mesg_flags |= H5O_MSG_FLAG_SHARED;
}
}
done:
HDassert((ret_value != TRUE)
|| ((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE
|| ((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_SOHM);
#ifndef NDEBUG
if(defer_flags & H5SM_WAS_DEFERRED)
HDassert(deferred_type == ((H5O_shared_t *)mesg)->type);
#endif
if(table && H5AC_unprotect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, cache_flags) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static herr_t
H5SM__incr_ref(void *record, void *_op_data, hbool_t *changed)
{
H5SM_sohm_t *message = (H5SM_sohm_t *) record;
H5SM_incr_ref_opdata *op_data = (H5SM_incr_ref_opdata *) _op_data;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(record);
HDassert(op_data);
HDassert(changed);
if(message->location == H5SM_IN_OH) {
HDassert(op_data->key && op_data->key->fheap);
if(H5HF_insert(op_data->key->fheap, op_data->key->encoding_size, op_data->key->encoding, &message->u.heap_loc.fheap_id) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap")
message->location = H5SM_IN_HEAP;
message->u.heap_loc.ref_count = 2;
}
else {
HDassert(message->location == H5SM_IN_HEAP);
++message->u.heap_loc.ref_count;
}
*changed = TRUE;
if(op_data)
op_data->fheap_id = message->u.heap_loc.fheap_id;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5SM__write_mesg(H5F_t *f, H5O_t *open_oh, H5SM_index_header_t *header,
hbool_t defer, unsigned type_id, void *mesg, unsigned *cache_flags_ptr)
{
H5SM_list_t *list = NULL;
H5SM_mesg_key_t key;
H5SM_list_cache_ud_t cache_udata;
H5O_shared_t shared;
hbool_t found = FALSE;
H5HF_t *fheap = NULL;
H5B2_t *bt2 = NULL;
size_t buf_size;
void * encoding_buf = NULL;
size_t empty_pos = UFAIL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_TAG(H5AC__SOHM_TAG)
HDassert(header);
HDassert(header->index_type != H5SM_BADTYPE);
HDassert(cache_flags_ptr);
if((buf_size = H5O_msg_raw_size(f, type_id, TRUE, mesg)) == 0)
HGOTO_ERROR(H5E_SOHM, H5E_BADSIZE, FAIL, "can't find message size")
if(NULL == (encoding_buf = H5MM_malloc(buf_size)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "can't allocate buffer for encoding")
if(H5O_msg_encode(f, type_id, TRUE, (unsigned char *)encoding_buf, mesg) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTENCODE, FAIL, "can't encode message to be shared")
if(NULL == (fheap = H5HF_open(f, header->heap_addr)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
key.file = f;
key.fheap = fheap;
key.encoding = encoding_buf;
key.encoding_size = buf_size;
key.message.hash = H5_checksum_lookup3(encoding_buf, buf_size, type_id);
key.message.location = H5SM_NO_LOC;
if(header->index_type == H5SM_LIST) {
size_t list_pos;
cache_udata.f = f;
cache_udata.header = header;
if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, H5AC_SOHM_LIST, header->index_addr, &cache_udata, defer ? H5AC__READ_ONLY_FLAG : H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM index")
if(H5SM__find_in_list(list, &key, &empty_pos, &list_pos) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to search for message in list")
if(defer) {
if(list_pos != UFAIL)
found = TRUE;
}
else {
if(list_pos != UFAIL) {
if(list->messages[list_pos].location == H5SM_IN_OH) {
if(H5HF_insert(fheap, key.encoding_size, key.encoding, &shared.u.heap_id) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap")
list->messages[list_pos].location = H5SM_IN_HEAP;
list->messages[list_pos].u.heap_loc.fheap_id = shared.u.heap_id;
list->messages[list_pos].u.heap_loc.ref_count = 2;
}
else {
HDassert(list->messages[list_pos].location == H5SM_IN_HEAP);
++(list->messages[list_pos].u.heap_loc.ref_count);
}
shared.u.heap_id = list->messages[list_pos].u.heap_loc.fheap_id;
found = TRUE;
}
}
}
else {
HDassert(header->index_type == H5SM_BTREE);
if(NULL == (bt2 = H5B2_open(f, header->index_addr, f)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
if(defer) {
htri_t bt2_find;
if((bt2_find = H5B2_find(bt2, &key, NULL, NULL)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "can't search for message in index")
found = (hbool_t)bt2_find;
}
else {
H5SM_incr_ref_opdata op_data;
op_data.key = &key;
if(H5B2_modify(bt2, &key, H5SM__incr_ref, &op_data) >= 0) {
shared.u.heap_id = op_data.fheap_id;
found = TRUE;
}
else
H5E_clear_stack(NULL);
}
}
if(found) {
shared.type = H5O_SHARE_TYPE_SOHM;
#ifdef H5_USING_MEMCHECKER
if(defer)
HDmemset(&shared.u, 0, sizeof(shared.u));
#endif
}
else {
htri_t share_in_ohdr;
if((share_in_ohdr = H5O_msg_can_share_in_ohdr(type_id)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "'share in ohdr' check returned error")
if(share_in_ohdr && open_oh) {
shared.type = H5O_SHARE_TYPE_HERE;
if(H5O_msg_get_crt_index(type_id, mesg, &shared.u.loc.index) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "unable to retrieve creation index")
if(defer)
shared.u.loc.oh_addr = HADDR_UNDEF;
else {
shared.u.loc.oh_addr = H5O_OH_GET_ADDR(open_oh);
key.message.location = H5SM_IN_OH;
key.message.u.mesg_loc = shared.u.loc;
}
}
else {
shared.type = H5O_SHARE_TYPE_SOHM;
if(!defer) {
if(H5HF_insert(fheap, key.encoding_size, key.encoding, &shared.u.heap_id) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap")
key.message.location = H5SM_IN_HEAP;
key.message.u.heap_loc.fheap_id = shared.u.heap_id;
key.message.u.heap_loc.ref_count = 1;
}
}
if(!defer) {
key.message.msg_type_id = type_id;
if(header->index_type == H5SM_LIST && header->num_messages >= header->list_max)
if(H5SM__convert_list_to_btree(f, header, &list, fheap, open_oh) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to convert list to B-tree")
if(header->index_type == H5SM_LIST) {
if(empty_pos == UFAIL) {
size_t pos;
if(H5SM__find_in_list(list, NULL, &empty_pos, &pos) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to search for message in list")
if(pos == UFAIL || empty_pos == UFAIL)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to find empty entry in list")
}
HDassert(list->messages[empty_pos].location == H5SM_NO_LOC);
HDassert(key.message.location != H5SM_NO_LOC);
list->messages[empty_pos] = key.message;
}
else {
HDassert(header->index_type == H5SM_BTREE);
if(NULL == bt2) {
if(NULL == (bt2 = H5B2_open(f, header->index_addr, f)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
}
if(H5B2_insert(bt2, &key) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "couldn't add SOHM to B-tree")
}
++(header->num_messages);
(*cache_flags_ptr) |= H5AC__DIRTIED_FLAG;
}
}
shared.file = f;
shared.msg_type_id = type_id;
if(H5O_msg_set_share(type_id, &shared, mesg) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_BADMESG, FAIL, "unable to set sharing information")
done:
if(fheap && H5HF_close(fheap) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close fractal heap")
if(bt2 && H5B2_close(bt2) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for SOHM index")
if(list && H5AC_unprotect(f, H5AC_SOHM_LIST, header->index_addr, list, defer ? H5AC__NO_FLAGS_SET : H5AC__DIRTIED_FLAG) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index")
if(encoding_buf)
encoding_buf = H5MM_xfree(encoding_buf);
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5SM_delete(H5F_t *f, H5O_t *open_oh, H5O_shared_t *sh_mesg)
{
H5SM_master_table_t *table = NULL;
unsigned cache_flags = H5AC__NO_FLAGS_SET;
H5SM_table_cache_ud_t cache_udata;
ssize_t index_num;
size_t mesg_size = 0;
void *mesg_buf = NULL;
void *native_mesg = NULL;
unsigned type_id;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_TAG(H5AC__SOHM_TAG, FAIL)
HDassert(f);
HDassert(H5F_addr_defined(H5F_SOHM_ADDR(f)));
HDassert(sh_mesg);
type_id = sh_mesg->msg_type_id;
cache_udata.f = f;
if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
if((index_num = H5SM_get_index(table, type_id)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "unable to find correct SOHM index")
if(H5SM__delete_from_index(f, open_oh, &(table->indexes[index_num]), sh_mesg, &cache_flags, &mesg_size, &mesg_buf) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete mesage from SOHM index")
if(H5AC_unprotect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, cache_flags) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
table = NULL;
if(mesg_buf) {
if(NULL == (native_mesg = H5O_msg_decode(f, open_oh, type_id, mesg_size, (const unsigned char *)mesg_buf)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTDECODE, FAIL, "can't decode shared message.")
if(H5O_msg_delete(f, open_oh, type_id, native_mesg) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "can't delete shared message.")
}
done:
if(table && H5AC_unprotect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, cache_flags) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
if(native_mesg)
H5O_msg_free(type_id, native_mesg);
if(mesg_buf)
mesg_buf = H5MM_xfree(mesg_buf);
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static herr_t
H5SM__find_in_list(const H5SM_list_t *list, const H5SM_mesg_key_t *key, size_t *empty_pos, size_t *pos)
{
size_t x;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(list);
HDassert(key || empty_pos);
if(empty_pos)
*empty_pos = UFAIL;
for(x = 0; x < list->header->list_max; x++) {
if(list->messages[x].location != H5SM_NO_LOC) {
int cmp;
if(H5SM__message_compare(key, &(list->messages[x]), &cmp) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTCOMPARE, FAIL, "can't compare message records")
if(0 == cmp) {
*pos = x;
HGOTO_DONE(SUCCEED)
}
}
else if(empty_pos && list->messages[x].location == H5SM_NO_LOC) {
*empty_pos = x;
empty_pos = NULL;
}
}
*pos = UFAIL;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5SM_get_hash_fh_cb(const void *obj, size_t obj_len, void *_udata)
{
H5SM_fh_ud_gh_t *udata = (H5SM_fh_ud_gh_t *)_udata;
FUNC_ENTER_NOAPI_NOINIT_NOERR
udata->hash = H5_checksum_lookup3(obj, obj_len, udata->type_id);
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5SM__decr_ref(void *record, void *op_data, hbool_t *changed)
{
H5SM_sohm_t *message = (H5SM_sohm_t *) record;
FUNC_ENTER_STATIC_NOERR
HDassert(record);
HDassert(op_data);
HDassert(changed);
if(message->location == H5SM_IN_HEAP) {
--message->u.heap_loc.ref_count;
*changed = TRUE;
}
if(op_data)
*(H5SM_sohm_t *)op_data = *message;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5SM__delete_from_index(H5F_t *f, H5O_t *open_oh, H5SM_index_header_t *header,
const H5O_shared_t *mesg, unsigned *cache_flags, size_t * mesg_size,
void ** encoded_mesg)
{
H5SM_list_t *list = NULL;
H5SM_mesg_key_t key;
H5SM_sohm_t message;
H5SM_sohm_t *message_ptr;
H5HF_t *fheap = NULL;
H5B2_t *bt2 = NULL;
size_t buf_size;
void *encoding_buf = NULL;
unsigned type_id;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_TAG(H5AC__SOHM_TAG)
HDassert(f);
HDassert(header);
HDassert(mesg);
HDassert(cache_flags);
HDassert(*encoded_mesg == NULL);
type_id = mesg->msg_type_id;
if(NULL == (fheap = H5HF_open(f, header->heap_addr)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
if(mesg->type == H5O_SHARE_TYPE_HERE) {
key.message.location = H5SM_IN_OH;
key.message.msg_type_id = type_id;
key.message.u.mesg_loc = mesg->u.loc;
}
else {
key.message.location = H5SM_IN_HEAP;
key.message.msg_type_id = type_id;
key.message.u.heap_loc.ref_count = 0;
key.message.u.heap_loc.fheap_id = mesg->u.heap_id;
}
if(H5SM__read_mesg(f, &key.message, fheap, open_oh, &buf_size, &encoding_buf) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
key.file = f;
key.fheap = fheap;
key.encoding = encoding_buf;
key.encoding_size = buf_size;
key.message.hash = H5_checksum_lookup3(encoding_buf, buf_size, type_id);
if(header->index_type == H5SM_LIST) {
H5SM_list_cache_ud_t cache_udata;
size_t list_pos;
cache_udata.f = f;
cache_udata.header = header;
if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, H5AC_SOHM_LIST, header->index_addr, &cache_udata, H5AC__NO_FLAGS_SET)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM index")
if(H5SM__find_in_list(list, &key, NULL, &list_pos) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "unable to search for message in list")
if(list_pos == UFAIL)
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "message not in index")
if(list->messages[list_pos].location == H5SM_IN_HEAP)
--(list->messages[list_pos].u.heap_loc.ref_count);
message_ptr = &list->messages[list_pos];
}
else {
HDassert(header->index_type == H5SM_BTREE);
if(NULL == (bt2 = H5B2_open(f, header->index_addr, f)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
if(H5B2_modify(bt2, &key, H5SM__decr_ref, &message) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "message not in index")
message_ptr = &message;
}
if(message_ptr->location == H5SM_IN_OH || message_ptr->u.heap_loc.ref_count == 0) {
H5SM_storage_loc_t old_loc = message_ptr->location;
--header->num_messages;
*cache_flags |= H5AC__DIRTIED_FLAG;
if(header->index_type == H5SM_LIST)
message_ptr->location = H5SM_NO_LOC;
else {
if(NULL == bt2) {
if(NULL == (bt2 = H5B2_open(f, header->index_addr, f)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
}
if(H5B2_remove(bt2, &key, NULL, NULL) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTREMOVE, FAIL, "unable to delete message from index")
}
if(old_loc == H5SM_IN_HEAP)
if(H5HF_remove(fheap, &(message_ptr->u.heap_loc.fheap_id)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTREMOVE, FAIL, "unable to remove message from heap")
*encoded_mesg = encoding_buf;
*mesg_size = buf_size;
if(header->num_messages == 0) {
if(list && H5AC_unprotect(f, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to release SOHM list")
list = NULL;
HDassert(fheap);
if(H5HF_close(fheap) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close fractal heap")
fheap = NULL;
if(H5SM__delete_index(f, header, TRUE) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "can't delete empty index")
}
else if(header->index_type == H5SM_BTREE && header->num_messages < header->btree_min) {
if(H5SM__convert_btree_to_list(f, header) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTINIT, FAIL, "unable to convert btree to list")
}
}
done:
if(list && H5AC_unprotect(f, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DIRTIED_FLAG) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index")
if(fheap && H5HF_close(fheap) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close fractal heap")
if(bt2 && H5B2_close(bt2) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for SOHM index")
if(encoding_buf && (NULL == *encoded_mesg || ret_value < 0)) {
encoding_buf = H5MM_xfree(encoding_buf);
*mesg_size = 0;
}
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5SM_get_info(const H5O_loc_t *ext_loc, H5P_genplist_t *fc_plist)
{
H5F_t *f = ext_loc->file;
H5O_shmesg_table_t sohm_table;
H5SM_master_table_t *table = NULL;
H5AC_ring_t orig_ring = H5AC_RING_INV;
unsigned tmp_sohm_nindexes;
htri_t status;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_TAG(H5AC__SOHM_TAG, FAIL)
HDassert(ext_loc);
HDassert(f);
HDassert(fc_plist);
if((status = H5O_msg_exists(ext_loc, H5O_SHMESG_ID)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "unable to read object header")
if(status) {
H5SM_table_cache_ud_t cache_udata;
unsigned index_flags[H5O_SHMESG_MAX_NINDEXES];
unsigned minsizes[H5O_SHMESG_MAX_NINDEXES];
unsigned sohm_l2b;
unsigned sohm_b2l;
unsigned u;
if(NULL == H5O_msg_read(ext_loc, H5O_SHMESG_ID, &sohm_table))
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "shared message info message not present")
HDmemset(index_flags, 0, sizeof(index_flags));
HDmemset(minsizes, 0, sizeof(minsizes));
H5F_SET_SOHM_ADDR(f, sohm_table.addr);
H5F_SET_SOHM_VERS(f, sohm_table.version);
H5F_SET_SOHM_NINDEXES(f, sohm_table.nindexes);
HDassert(H5F_addr_defined(H5F_SOHM_ADDR(f)));
HDassert(H5F_SOHM_NINDEXES(f) > 0 && H5F_SOHM_NINDEXES(f) <= H5O_SHMESG_MAX_NINDEXES);
cache_udata.f = f;
H5AC_set_ring(H5AC_RING_USER, &orig_ring);
if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
sohm_l2b = (unsigned)table->indexes[0].list_max;
sohm_b2l = (unsigned)table->indexes[0].btree_min;
for(u = 0; u < table->num_indexes; ++u) {
index_flags[u] = table->indexes[u].mesg_types;
minsizes[u] = (unsigned)table->indexes[u].min_mesg_size;
HDassert(sohm_l2b == table->indexes[u].list_max);
HDassert(sohm_b2l == table->indexes[u].btree_min);
if(index_flags[u] & H5O_SHMESG_ATTR_FLAG)
H5F_SET_STORE_MSG_CRT_IDX(f, TRUE);
}
tmp_sohm_nindexes = H5F_SOHM_NINDEXES(f);
if(H5P_set(fc_plist, H5F_CRT_SHMSG_NINDEXES_NAME, &tmp_sohm_nindexes) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTSET, FAIL, "can't set number of SOHM indexes")
if(H5P_set(fc_plist, H5F_CRT_SHMSG_INDEX_TYPES_NAME, index_flags) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTSET, FAIL, "can't set type flags for indexes")
if(H5P_set(fc_plist, H5F_CRT_SHMSG_INDEX_MINSIZE_NAME, minsizes) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTSET, FAIL, "can't set type flags for indexes")
if(H5P_set(fc_plist, H5F_CRT_SHMSG_LIST_MAX_NAME, &sohm_l2b) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't set SOHM cutoff in property list")
if(H5P_set(fc_plist, H5F_CRT_SHMSG_BTREE_MIN_NAME, &sohm_b2l) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't set SOHM cutoff in property list")
}
else {
H5F_SET_SOHM_ADDR(f, HADDR_UNDEF);
H5F_SET_SOHM_VERS(f, 0);
H5F_SET_SOHM_NINDEXES(f, 0);
tmp_sohm_nindexes = H5F_SOHM_NINDEXES(f);
if(H5P_set(fc_plist, H5F_CRT_SHMSG_NINDEXES_NAME, &tmp_sohm_nindexes) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTSET, FAIL, "can't set number of SOHM indexes")
}
done:
if(orig_ring != H5AC_RING_INV)
H5AC_set_ring(orig_ring, NULL);
if(table && H5AC_unprotect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5SM_reconstitute(H5O_shared_t *sh_mesg, H5F_t *f, unsigned msg_type_id,
H5O_fheap_id_t heap_id)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(sh_mesg);
sh_mesg->type = H5O_SHARE_TYPE_SOHM;
sh_mesg->file = f;
sh_mesg->msg_type_id = msg_type_id;
sh_mesg->u.heap_id = heap_id;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5SM_get_refcount_bt2_cb(const void *_record, void *_op_data)
{
const H5SM_sohm_t *record = (const H5SM_sohm_t *)_record;
H5SM_sohm_t *op_data = (H5SM_sohm_t *)_op_data;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(record);
HDassert(op_data);
*op_data = *record;
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5SM_get_refcount(H5F_t *f, unsigned type_id, const H5O_shared_t *sh_mesg,
hsize_t *ref_count)
{
H5HF_t *fheap = NULL;
H5B2_t *bt2 = NULL;
H5SM_master_table_t *table = NULL;
H5SM_table_cache_ud_t tbl_cache_udata;
H5SM_list_t *list = NULL;
H5SM_index_header_t *header=NULL;
H5SM_mesg_key_t key;
H5SM_sohm_t message;
ssize_t index_num;
size_t buf_size;
void * encoding_buf = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT_TAG(H5AC__SOHM_TAG)
HDassert(f);
HDassert(sh_mesg);
HDassert(ref_count);
tbl_cache_udata.f = f;
if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &tbl_cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
if((index_num = H5SM_get_index(table, type_id)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "unable to find correct SOHM index")
header = &(table->indexes[index_num]);
if(NULL == (fheap = H5HF_open(f, header->heap_addr)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
key.message.location = H5SM_IN_HEAP;
key.message.u.heap_loc.fheap_id = sh_mesg->u.heap_id;
key.message.u.heap_loc.ref_count = 0;
if(H5SM__read_mesg(f, &key.message, fheap, NULL, &buf_size, &encoding_buf) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
key.file = f;
key.fheap = fheap;
key.encoding = encoding_buf;
key.encoding_size = buf_size;
key.message.hash = H5_checksum_lookup3(encoding_buf, buf_size, type_id);
if(header->index_type == H5SM_LIST) {
H5SM_list_cache_ud_t lst_cache_udata;
size_t list_pos;
lst_cache_udata.f = f;
lst_cache_udata.header = header;
if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, H5AC_SOHM_LIST, header->index_addr, &lst_cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM index")
if(H5SM__find_in_list(list, &key, NULL, &list_pos) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "unable to search for message in list")
if(list_pos == UFAIL)
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "message not in index")
message = list->messages[list_pos];
}
else {
htri_t msg_exists;
HDassert(header->index_type == H5SM_BTREE);
if(NULL == (bt2 = H5B2_open(f, header->index_addr, f)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
if((msg_exists = H5B2_find(bt2, &key, H5SM_get_refcount_bt2_cb, &message)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "error finding message in index")
if(!msg_exists)
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "message not in index")
}
HDassert(message.location == H5SM_IN_HEAP);
*ref_count = message.u.heap_loc.ref_count;
done:
if(list && H5AC_unprotect(f, H5AC_SOHM_LIST, header->index_addr, list, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index")
if(table && H5AC_unprotect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
if(fheap && H5HF_close(fheap) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close fractal heap")
if(bt2 && H5B2_close(bt2) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for SOHM index")
if(encoding_buf)
encoding_buf = H5MM_xfree(encoding_buf);
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
static herr_t
H5SM__read_iter_op(H5O_t *oh, H5O_mesg_t *mesg, unsigned sequence,
unsigned H5_ATTR_UNUSED *oh_modified, void *_udata)
{
H5SM_read_udata_t *udata = (H5SM_read_udata_t *) _udata;
herr_t ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC
HDassert(oh);
HDassert(mesg);
HDassert(udata);
HDassert(NULL == udata->encoding_buf);
if(sequence == udata->idx) {
if(mesg->dirty)
if(H5O_msg_flush(udata->file, oh, mesg) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTENCODE, H5_ITER_ERROR, "unable to encode object header message")
udata->buf_size = mesg->raw_size;
HDassert(udata->buf_size);
if(NULL == (udata->encoding_buf = H5MM_malloc(udata->buf_size)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed")
H5MM_memcpy(udata->encoding_buf, mesg->raw, udata->buf_size);
ret_value = H5_ITER_STOP;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5SM__read_mesg_fh_cb(const void *obj, size_t obj_len, void *_udata)
{
H5SM_read_udata_t *udata = (H5SM_read_udata_t *)_udata;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
if(NULL == (udata->encoding_buf = H5MM_malloc(obj_len)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "memory allocation failed")
H5MM_memcpy(udata->encoding_buf, obj, obj_len);
udata->buf_size = obj_len;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5SM__read_mesg(H5F_t *f, const H5SM_sohm_t *mesg, H5HF_t *fheap,
H5O_t *open_oh, size_t *encoding_size , void ** encoded_mesg )
{
H5SM_read_udata_t udata;
H5O_loc_t oloc;
H5O_t *oh = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_TAG(H5AC__SOHM_TAG)
HDassert(f);
HDassert(mesg);
HDassert(fheap);
udata.file = f;
udata.idx = mesg->u.mesg_loc.index;
udata.encoding_buf = NULL;
udata.idx = 0;
if(mesg->location == H5SM_IN_OH) {
const H5O_msg_class_t *type = NULL;
H5O_mesg_operator_t op;
type = H5O_msg_class_g[mesg->msg_type_id];
HDassert(type);
if(H5O_loc_reset(&oloc) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTRESET, FAIL, "unable to initialize location")
if(NULL == open_oh || mesg->u.mesg_loc.oh_addr != H5O_OH_GET_ADDR(open_oh)) {
oloc.file = f;
oloc.addr = mesg->u.mesg_loc.oh_addr;
if(H5O_open(&oloc) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, FAIL, "unable to open object header")
if(NULL == (oh = H5O_protect(&oloc, H5AC__READ_ONLY_FLAG, FALSE)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load object header")
}
else
oh = open_oh;
op.op_type = H5O_MESG_OP_LIB;
op.u.lib_op = H5SM__read_iter_op;
if((ret_value = H5O__msg_iterate_real(f, oh, type, &op, &udata)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_BADITER, FAIL, "unable to iterate over object header messages")
}
else {
HDassert(mesg->location == H5SM_IN_HEAP);
if(H5HF_op(fheap, &(mesg->u.heap_loc.fheap_id), H5SM__read_mesg_fh_cb, &udata) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, FAIL, "can't read message from fractal heap.")
}
HDassert(udata.encoding_buf);
HDassert(udata.buf_size);
*encoded_mesg = udata.encoding_buf;
*encoding_size = udata.buf_size;
done:
if(oh && oh != open_oh) {
if(oh && H5O_unprotect(&oloc, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
if(H5O_close(&oloc, NULL) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "unable to close object header")
}
if(ret_value < 0 && udata.encoding_buf)
udata.encoding_buf = H5MM_xfree(udata.encoding_buf);
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5SM_table_free(H5SM_master_table_t *table)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(table);
HDassert(table->indexes);
table->indexes = H5FL_ARR_FREE(H5SM_index_header_t, table->indexes);
table = H5FL_FREE(H5SM_master_table_t, table);
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5SM_list_free(H5SM_list_t *list)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(list);
HDassert(list->messages);
list->messages = H5FL_ARR_FREE(H5SM_sohm_t, list->messages);
list = H5FL_FREE(H5SM_list_t, list);
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5SM_table_debug(H5F_t *f, haddr_t table_addr, FILE *stream, int indent,
int fwidth, unsigned table_vers, unsigned num_indexes)
{
H5SM_master_table_t *table = NULL;
H5SM_table_cache_ud_t cache_udata;
unsigned x;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_TAG(H5AC__SOHM_TAG, FAIL)
HDassert(f);
HDassert(table_addr != HADDR_UNDEF);
HDassert(stream);
HDassert(indent >= 0);
HDassert(fwidth >= 0);
if(table_vers == UFAIL)
table_vers = H5F_SOHM_VERS(f);
else if(table_vers != H5F_SOHM_VERS(f))
HDfprintf(stream, "*** SOHM TABLE VERSION DOESN'T MATCH VERSION IN SUPERBLOCK!\n");
if(num_indexes == UFAIL)
num_indexes = H5F_SOHM_NINDEXES(f);
else if(num_indexes != H5F_SOHM_NINDEXES(f))
HDfprintf(stream, "*** NUMBER OF SOHM INDEXES DOESN'T MATCH VALUE IN SUPERBLOCK!\n");
if(table_vers > HDF5_SHAREDHEADER_VERSION)
HGOTO_ERROR(H5E_SOHM, H5E_BADVALUE, FAIL, "unknown shared message table version")
if(num_indexes == 0 || num_indexes > H5O_SHMESG_MAX_NINDEXES)
HGOTO_ERROR(H5E_SOHM, H5E_BADVALUE, FAIL, "number of indexes must be between 1 and H5O_SHMESG_MAX_NINDEXES")
cache_udata.f = f;
if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, H5AC_SOHM_TABLE, table_addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
HDfprintf(stream, "%*sShared Message Master Table...\n", indent, "");
for(x = 0; x < num_indexes; ++x) {
HDfprintf(stream, "%*sIndex %d...\n", indent, "", x);
HDfprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth,
"SOHM Index Type:",
(table->indexes[x].index_type == H5SM_LIST ? "List" :
(table->indexes[x].index_type == H5SM_BTREE ? "B-Tree" : "Unknown")));
HDfprintf(stream, "%*s%-*s %a\n", indent + 3, "", fwidth,
"Address of index:", table->indexes[x].index_addr);
HDfprintf(stream, "%*s%-*s %a\n", indent + 3, "", fwidth,
"Address of index's heap:", table->indexes[x].heap_addr);
HDfprintf(stream, "%*s%-*s 0x%08x\n", indent + 3, "", fwidth,
"Message type flags:", table->indexes[x].mesg_types);
HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", fwidth,
"Minimum size of messages:", table->indexes[x].min_mesg_size);
HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", fwidth,
"Number of messages:", table->indexes[x].num_messages);
HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", fwidth,
"Maximum list size:", table->indexes[x].list_max);
HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", fwidth,
"Minimum B-tree size:", table->indexes[x].btree_min);
}
done:
if(table && H5AC_unprotect(f, H5AC_SOHM_TABLE, table_addr, table, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5SM_list_debug(H5F_t *f, haddr_t list_addr, FILE *stream, int indent,
int fwidth, haddr_t table_addr)
{
H5SM_master_table_t *table = NULL;
H5SM_list_t *list = NULL;
H5SM_list_cache_ud_t lst_cache_udata;
H5SM_table_cache_ud_t tbl_cache_udata;
H5HF_t *fh = NULL;
unsigned index_num;
unsigned x;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_TAG(H5AC__SOHM_TAG, FAIL)
HDassert(f);
HDassert(list_addr != HADDR_UNDEF);
HDassert(stream);
HDassert(indent >= 0);
HDassert(fwidth >= 0);
tbl_cache_udata.f = f;
if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, H5AC_SOHM_TABLE, table_addr, &tbl_cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
index_num = table->num_indexes;
for(x = 0; x < table->num_indexes; x++) {
if(H5F_addr_eq(table->indexes[x].index_addr, list_addr)) {
index_num = x;
break;
}
}
if(x == table->num_indexes)
HGOTO_ERROR(H5E_SOHM, H5E_BADVALUE, FAIL, "list address doesn't match address for any indices in table")
lst_cache_udata.f = f;
lst_cache_udata.header = &(table->indexes[index_num]);
if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, H5AC_SOHM_LIST, list_addr, &lst_cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM index")
if(H5F_addr_defined(table->indexes[index_num].heap_addr))
if(NULL == (fh = H5HF_open(f, table->indexes[index_num].heap_addr)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open SOHM heap")
HDfprintf(stream, "%*sShared Message List Index...\n", indent, "");
for(x = 0; x < table->indexes[index_num].num_messages; ++x) {
HDfprintf(stream, "%*sShared Object Header Message %d...\n", indent, "", x);
HDfprintf(stream, "%*s%-*s %08lu\n", indent + 3, "", fwidth,
"Hash value:", (unsigned long)list->messages[x].hash);
if(list->messages[x].location == H5SM_IN_HEAP) {
HDassert(fh);
HDfprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth,
"Location:", "in heap");
HDfprintf(stream, "%*s%-*s 0x%Zx\n", indent + 3, "", fwidth,
"Heap ID:", list->messages[x].u.heap_loc.fheap_id);
HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", fwidth,
"Reference count:", list->messages[x].u.heap_loc.ref_count);
}
else if(list->messages[x].location == H5SM_IN_OH) {
HDfprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth,
"Location:", "in object header");
HDfprintf(stream, "%*s%-*s %a\n", indent + 3, "", fwidth,
"Object header address:", list->messages[x].u.mesg_loc.oh_addr);
HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", fwidth,
"Message creation index:", list->messages[x].u.mesg_loc.oh_addr);
HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", fwidth,
"Message type ID:", list->messages[x].msg_type_id);
}
else
HDfprintf(stream, "%*s%-*s %s\n", indent + 3, "", fwidth,
"Location:", "invalid");
}
done:
if(fh && H5HF_close(fh) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "unable to close SOHM heap")
if(list && H5AC_unprotect(f, H5AC_SOHM_LIST, list_addr, list, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index")
if(table && H5AC_unprotect(f, H5AC_SOHM_TABLE, table_addr, table, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5SM_ih_size(H5F_t *f, hsize_t *hdr_size, H5_ih_info_t *ih_info)
{
H5SM_master_table_t *table = NULL;
H5SM_table_cache_ud_t cache_udata;
H5HF_t *fheap = NULL;
H5B2_t *bt2 = NULL;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_TAG(H5AC__SOHM_TAG, FAIL)
HDassert(f);
HDassert(H5F_addr_defined(H5F_SOHM_ADDR(f)));
HDassert(hdr_size);
HDassert(ih_info);
cache_udata.f = f;
if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), &cache_udata, H5AC__READ_ONLY_FLAG)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table")
*hdr_size = table->table_size;
for(u = 0; u < table->num_indexes; u++) {
if(table->indexes[u].index_type == H5SM_BTREE) {
if(H5F_addr_defined(table->indexes[u].index_addr)) {
if(NULL == (bt2 = H5B2_open(f, table->indexes[u].index_addr, f)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index")
if(H5B2_size(bt2, &(ih_info->index_size)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't retrieve B-tree storage info")
if(H5B2_close(bt2) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for SOHM index")
bt2 = NULL;
}
}
else {
HDassert(table->indexes[u].index_type == H5SM_LIST);
ih_info->index_size += table->indexes[u].list_size;
}
if(H5F_addr_defined(table->indexes[u].heap_addr)) {
if(NULL == (fheap = H5HF_open(f, table->indexes[u].heap_addr)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
if(H5HF_size(fheap, &(ih_info->heap_size)) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't retrieve fractal heap storage info")
if(H5HF_close(fheap) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close fractal heap")
fheap = NULL;
}
}
done:
if(fheap && H5HF_close(fheap) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close fractal heap")
if(bt2 && H5B2_close(bt2) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for SOHM index")
if(table && H5AC_unprotect(f, H5AC_SOHM_TABLE, H5F_SOHM_ADDR(f), table, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM master table")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}