diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2007-05-14 20:24:08 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2007-05-14 20:24:08 (GMT) |
commit | 31ff357f3190a869147378a9a136510be2caafd7 (patch) | |
tree | 5220b17a8e4b6c434b799108719a1dc15d6c0326 /src/H5SMbtree2.c | |
parent | 1726061075e9adc99ac2286fb542438acc79c4ab (diff) | |
download | hdf5-31ff357f3190a869147378a9a136510be2caafd7.zip hdf5-31ff357f3190a869147378a9a136510be2caafd7.tar.gz hdf5-31ff357f3190a869147378a9a136510be2caafd7.tar.bz2 |
[svn-r13753] Description:
Check in "unique, but sharable" optimization to ISOHM code, which
allows object header messages that are only used in one object to remain in
the sole user's header, but migrates messages that are used in more than one
header into the ISOHM heap.
Tested on:
Mac OS X/32 10.4.9 (amazon)
FreeBSD/32 6.2 (duty)
Linux/32 2.6 (chicago)
Linux/64 2.6 (chicago2)
Diffstat (limited to 'src/H5SMbtree2.c')
-rwxr-xr-x | src/H5SMbtree2.c | 292 |
1 files changed, 157 insertions, 135 deletions
diff --git a/src/H5SMbtree2.c b/src/H5SMbtree2.c index c85770dd..3cd2f23 100755 --- a/src/H5SMbtree2.c +++ b/src/H5SMbtree2.c @@ -36,16 +36,20 @@ /* Local Typedefs */ /******************/ -/* Udata struct for call to H5SM_btree_compare_cb */ +/* Udata struct for calls to H5SM_btree_compare_cb and H5SM_compare_iter_op*/ typedef struct H5SM_compare_udata_t { - H5SM_mesg_key_t *key; /* Key; compare this against record in heap */ - herr_t ret; /* Return value; set this to result of memcmp */ + const H5SM_mesg_key_t *key; /* Key; compare this against stored message */ + H5O_msg_crt_idx_t idx; /* Index of the message in the OH, if applicable */ + unsigned type_id; /* Type ID of the type being compared */ + herr_t ret; /* Return value; set this to result of memcmp */ } H5SM_compare_udata_t; + /********************/ /* Local Prototypes */ /********************/ +/* v2 B-tree callbacks */ static herr_t H5SM_btree_compare_cb(const void *obj, size_t obj_len, void *_udata); static herr_t H5SM_btree_store(void *native, const void *udata); static herr_t H5SM_btree_retrieve(void *udata, const void *native); @@ -98,21 +102,85 @@ H5SM_btree_compare_cb(const void *obj, size_t obj_len, void *_udata) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_btree_compare_cb) /* If the encoding sizes are different, it's not the same object */ - if(udata->key->encoding_size != obj_len) { - if(udata->key->encoding_size > obj_len) - udata->ret = 1; - else - udata->ret = -1; - } else { + if(udata->key->encoding_size > obj_len) + udata->ret = 1; + else if(udata->key->encoding_size < obj_len) + udata->ret = -1; + else /* Sizes are the same. Return result of memcmp */ udata->ret = HDmemcmp(udata->key->encoding, obj, obj_len); - } FUNC_LEAVE_NOAPI(ret_value) } /* end H5SM_btree_compare_cb() */ /*------------------------------------------------------------------------- + * Function: H5SM_compare_iter_op + * + * Purpose: OH iteration callback to compare a key against a message in + * an OH + * + * Return: 0 if this is not the message we're searching for + * 1 if this is the message we're searching for (with memcmp + * result returned in udata) + * negative on error + * + * Programmer: James Laird + * Wednesday, February 7, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_compare_iter_op(const void *_mesg, unsigned idx, void *_udata) +{ + H5SM_compare_udata_t *udata = (H5SM_compare_udata_t *) _udata; + unsigned char *buf = NULL; + herr_t ret_value = H5_ITER_CONT; + + FUNC_ENTER_NOAPI_NOINIT(H5SM_compare_iter_op) + + /* + * Check arguments. + */ + HDassert(_mesg); + HDassert(udata && udata->key); + + /* Check the creation index for this message */ + if(idx == udata->idx) { + size_t raw_size; + + /* Retrieve the length of the unshared version of the message */ + raw_size = H5O_msg_raw_size(udata->key->file, udata->type_id, TRUE, _mesg); + HDassert(raw_size > 0); + + if(udata->key->encoding_size > raw_size) + udata->ret = 1; + else if(udata->key->encoding_size < raw_size) + udata->ret = -1; + else { + if(NULL == (buf = HDmalloc(raw_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed") + + /* JAMES: is there a faster way to get the encoded value here? Do we already have a raw value? */ + if(H5O_msg_encode(udata->key->file, udata->type_id, TRUE, buf, _mesg) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, H5_ITER_ERROR, "unable to encode message from object header") + + udata->ret = HDmemcmp(udata->key->encoding, buf, raw_size); + } /* end else */ + + /* Indicate that we found the message we were looking for */ + ret_value = H5_ITER_STOP; + } /* end if */ + +done: + if(buf) + HDfree(buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_compare_iter_op() */ + + +/*------------------------------------------------------------------------- * Function: H5SM_message_compare * * Purpose: Determine whether the search key rec1 represents a shared @@ -133,52 +201,80 @@ H5SM_message_compare(const void *rec1, const void *rec2) { const H5SM_mesg_key_t *key = (const H5SM_mesg_key_t *) rec1; const H5SM_sohm_t *mesg = (const H5SM_sohm_t *) rec2; - int64_t hash_diff; /* Has to be able to hold two 32-bit values */ herr_t ret_value = 0; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_compare) - /* JAMES: might be able to spare a sentinel byte instead of worrying about - * refcounts. Here, we need to find a deleted message in a B-tree to - * actually delete it. - */ - /* JAMES HDassert(mesg->ref_count > 0); */ - /* If the key has an fheap ID, we're looking for a message that's * already in the index; if the fheap ID matches, we've found the message * and can stop immediately. + * Likewise, if the message has an OH location that is matched by the + * message in the index, we've found the message. */ - if(key->message.fheap_id == mesg->fheap_id) - HGOTO_DONE(0); - - hash_diff = key->message.hash; - hash_diff -= mesg->hash; + if(mesg->location == H5SM_IN_HEAP && key->message.location == H5SM_IN_HEAP) { + if(key->message.u.heap_loc.fheap_id == mesg->u.heap_loc.fheap_id) + HGOTO_DONE(0); + } /* end if */ + else if(mesg->location == H5SM_IN_OH && key->message.location == H5SM_IN_OH) { + if(key->message.u.mesg_loc.oh_addr == mesg->u.mesg_loc.oh_addr && + key->message.u.mesg_loc.index == mesg->u.mesg_loc.index && + key->message.msg_type_id == mesg->msg_type_id) + HGOTO_DONE(0); + } /* end if */ + /* Compare hash values */ + if(key->message.hash > mesg->hash) + ret_value = 1; + else if(key->message.hash < mesg->hash) + ret_value = -1; /* If the hash values match, make sure the messages are really the same */ - if(0 == hash_diff) { - /* Hash values match; compare the encoded message with the one in - * the heap. - */ - H5SM_compare_udata_t udata; - herr_t ret; + else { + /* Hash values match; compare the encoded message with the one in + * the index. + */ + H5SM_compare_udata_t udata; + herr_t status; + HDassert(key->message.hash == mesg->hash); HDassert(key->encoding_size > 0 && key->encoding); - /* Casting away const OK. -JML */ + + /* Set up user data for callback */ udata.key = key; - /* Call heap op routine with comparison callback */ - ret = H5HF_op(key->fheap, H5AC_dxpl_id, &(mesg->fheap_id), H5SM_btree_compare_cb, &udata); - HDassert(ret >= 0); + /* Compare the encoded message with either the message in the heap or + * the message in an object header. + */ + if(mesg->location == H5SM_IN_HEAP) { + /* Call heap op routine with comparison callback */ + status = H5HF_op(key->fheap, H5AC_dxpl_id, &(mesg->u.heap_loc.fheap_id), H5SM_btree_compare_cb, &udata); + HDassert(status >= 0); + } /* end if */ + else { + H5O_loc_t oloc; /* Object owning the message */ + + /* Sanity checks */ + HDassert(key->file); + HDassert(mesg->location == H5SM_IN_OH); + + /* Reset the object location */ + status = H5O_loc_reset(&oloc); + HDassert(status >= 0); + + /* Set up object location */ + oloc.file = key->file; + oloc.addr = mesg->u.mesg_loc.oh_addr; + + /* Finish setting up user data for iterator */ + udata.idx = mesg->u.mesg_loc.index; + udata.type_id = mesg->msg_type_id; + + /* JAMES: is this okay? */ + status = H5O_msg_iterate(&oloc, mesg->msg_type_id, H5SM_compare_iter_op, &udata, key->dxpl_id); + HDassert(status >= 0); + } /* end else */ ret_value = udata.ret; } /* end if */ - else { - /* Compress 64-bit hash_diff to fit in an herr_t */ - if(hash_diff > 0) - ret_value = 1; - else - ret_value = -1; - } done: FUNC_LEAVE_NOAPI(ret_value) @@ -263,92 +359,22 @@ H5SM_btree_debug(FILE *stream, const H5F_t UNUSED *f, hid_t UNUSED dxpl_id, FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_btree_debug) - HDfprintf(stream, "%*s%-*s {%a, %lo, %Hx}\n", indent, "", fwidth, "Shared Message:", - sohm->fheap_id, sohm->hash, sohm->ref_count); + if(sohm->location == H5SM_IN_HEAP) + HDfprintf(stream, "%*s%-*s {%a, %lo, %Hx}\n", indent, "", fwidth, + "Shared Message in heap:", + sohm->u.heap_loc.fheap_id, sohm->hash, sohm->u.heap_loc.ref_count); + else { + HDassert(sohm->location == H5SM_IN_OH); + HDfprintf(stream, "%*s%-*s {%a, %lo, %Hx, %Hx}\n", indent, "", fwidth, + "Shared Message in OH:", + sohm->u.mesg_loc.oh_addr, sohm->hash, sohm->msg_type_id, sohm->u.mesg_loc.index); + } /* end else */ FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5SM_btree_debug */ /*------------------------------------------------------------------------- - * Function: H5SM_incr_ref - * - * Purpose: Increment the reference count for a SOHM message and return - * the message's heap ID. - * - * The message pointer is actually returned via op_data, which - * should be a pointer to a H5SM_fheap_id_t. - * - * Return: Non-negative on success - * Negative on failure - * - * Programmer: James Laird - * Monday, November 6, 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5SM_incr_ref(void *record, void *op_data, hbool_t *changed) -{ - H5SM_sohm_t *message = (H5SM_sohm_t *) record; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_incr_ref) - - HDassert(record); - HDassert(op_data); - HDassert(changed); - - ++message->ref_count; - *changed = TRUE; - - if(op_data) - *(H5O_fheap_id_t *)op_data = message->fheap_id; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5SM_incr_ref() */ - - -/*------------------------------------------------------------------------- - * Function: H5SM_decr_ref - * - * Purpose: Decrement the reference count for a SOHM message. Doesn't - * remove the record from the B-tree even if the refcount - * reaches zero. - * - * The new message is returned through op_data. If its - * reference count is zero, the calling function should - * remove this record from the B-tree. - * - * Return: Non-negative on success - * Negative on failure - * - * Programmer: James Laird - * Monday, November 6, 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5SM_decr_ref(void *record, void *op_data, hbool_t *changed) -{ - H5SM_sohm_t *message = (H5SM_sohm_t *) record; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_decr_ref) - - HDassert(record); - HDassert(op_data); - HDassert(changed); - - --message->ref_count; - *changed = TRUE; - - if(op_data) - *(H5SM_sohm_t *)op_data = *message; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5SM_decr_ref() */ - - -/*------------------------------------------------------------------------- * Function: H5SM_btree_convert_to_list_op * * Purpose: An H5B2_remove_t callback function to convert a SOHM @@ -367,29 +393,25 @@ H5SM_decr_ref(void *record, void *op_data, hbool_t *changed) herr_t H5SM_btree_convert_to_list_op(const void * record, void *op_data) { - const H5SM_sohm_t *message = (const H5SM_sohm_t *) record; - const H5SM_list_t *list = (const H5SM_list_t *) op_data; - hsize_t x; + const H5SM_sohm_t *message = (const H5SM_sohm_t *)record; + const H5SM_list_t *list = (const H5SM_list_t *)op_data; + size_t mesg_idx; /* Index of message to modify */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_btree_convert_to_list_op) + /* Sanity checks */ HDassert(record); HDassert(op_data); - /* Insert this message into the list */ - for(x=0; x<list->header->list_max; x++) - { - if(list->messages[x].ref_count == 0) - { - HDmemcpy(&(list->messages[x]), message, sizeof(H5SM_sohm_t)); - HDassert(list->messages[x].ref_count > 0); - break; - } - } + /* Get the message index, and increment the # of messages in list */ + mesg_idx = list->header->num_messages++; + HDassert(list->header->num_messages <= list->header->list_max); - /* Increment the number of messages in the list */ - ++list->header->num_messages; + /* Insert this message at the end of the list */ + HDassert(list->messages[mesg_idx].location == H5SM_NO_LOC); + HDassert(message->location != H5SM_NO_LOC); + HDmemcpy(&(list->messages[mesg_idx]), message, sizeof(H5SM_sohm_t)); FUNC_LEAVE_NOAPI(SUCCEED) -} +} /* end H5SM_btree_convert_to_list_op() */ |