summaryrefslogtreecommitdiffstats
path: root/src/H5SMbtree2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5SMbtree2.c')
-rwxr-xr-xsrc/H5SMbtree2.c292
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() */