diff options
Diffstat (limited to 'src/H5SMmessage.c')
-rw-r--r-- | src/H5SMmessage.c | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/src/H5SMmessage.c b/src/H5SMmessage.c new file mode 100644 index 0000000..9a214ea --- /dev/null +++ b/src/H5SMmessage.c @@ -0,0 +1,358 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5O_PACKAGE /*suppress error about including H5Opkg */ +#define H5SM_PACKAGE /*suppress error about including H5SMpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Opkg.h" /* Object Headers */ +#include "H5SMpkg.h" /* Shared object header messages */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + +/* Udata struct for calls to H5SM_compare_cb and H5SM_compare_iter_op*/ +typedef struct H5SM_compare_udata_t { + 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 */ + herr_t ret; /* Return value; set this to result of memcmp */ +} H5SM_compare_udata_t; + + +/********************/ +/* Local Prototypes */ +/********************/ +static herr_t H5SM_compare_cb(const void *obj, size_t obj_len, void *udata); +static herr_t H5SM_compare_iter_op(H5O_t *oh, H5O_mesg_t *mesg, unsigned sequence, + hbool_t *oh_modified, void *udata); + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_compare_cb + * + * Purpose: Callback for H5HF_op, used in H5SM_message_compare below. + * Determines whether the search key passed in in _UDATA is + * equal to OBJ or not. + * + * Passes back the result in _UDATA->RET + * + * Return: Negative on error, non-negative on success + * + * Programmer: James Laird + * Monday, January 8, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_compare_cb(const void *obj, size_t obj_len, void *_udata) +{ + H5SM_compare_udata_t *udata = (H5SM_compare_udata_t *)_udata; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_compare_cb) + + /* If the encoding sizes are different, it's not the same object */ + 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(SUCCEED) +} /* end H5SM_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(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned sequence, + hbool_t UNUSED *oh_modified, void *_udata/*in,out*/) +{ + H5SM_compare_udata_t *udata = (H5SM_compare_udata_t *) _udata; + herr_t ret_value = H5_ITER_CONT; + + FUNC_ENTER_NOAPI_NOINIT(H5SM_compare_iter_op) + + /* + * Check arguments. + */ + HDassert(oh); + HDassert(mesg); + HDassert(udata && udata->key); + + /* Check the creation index for this message */ + if(sequence == udata->idx) { + size_t aligned_encoded_size = H5O_ALIGN_OH(oh, udata->key->encoding_size); + + /* Sanity check the message's length */ + HDassert(mesg->raw_size > 0); + + if(aligned_encoded_size > mesg->raw_size) + udata->ret = 1; + else if(aligned_encoded_size < mesg->raw_size) + udata->ret = -1; + else { + /* Check if the message is dirty & flush it to the object header if so */ + if(mesg->dirty) + if(H5O_msg_flush(udata->key->file, oh, mesg) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTENCODE, H5_ITER_ERROR, "unable to encode object header message") + + HDassert(udata->key->encoding_size <= mesg->raw_size); + udata->ret = HDmemcmp(udata->key->encoding, mesg->raw, udata->key->encoding_size); + } /* end else */ + + /* Indicate that we found the message we were looking for */ + ret_value = H5_ITER_STOP; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_compare_iter_op() */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_message_compare + * + * Purpose: Determine whether the search key rec1 represents a shared + * message that is equal to rec2 or not, and if not, whether + * rec1 is "greater than" or "less than" rec2. + * + * Return: 0 if rec1 == rec2 + * Negative if rec1 < rec2 + * Positive if rec1 > rec2 + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +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; + herr_t ret_value = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_compare) + + /* 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(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 */ + 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); + + /* Set up user data for callback */ + udata.key = key; + + /* 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, key->dxpl_id, &(mesg->u.heap_loc.fheap_id), H5SM_compare_cb, &udata); + HDassert(status >= 0); + } /* end if */ + else { + H5O_loc_t oloc; /* Object owning the message */ + H5O_mesg_operator_t op; /* Message operator */ + + /* 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; + + /* Locate the right message and compare with it */ + op.op_type = H5O_MESG_OP_LIB; + op.u.lib_op = H5SM_compare_iter_op; + status = H5O_msg_iterate(&oloc, mesg->msg_type_id, &op, &udata, key->dxpl_id); + HDassert(status >= 0); + } /* end else */ + + ret_value = udata.ret; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_message_compare */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_message_encode + * + * Purpose: Serialize a H5SM_sohm_t struct into a buffer RAW. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5SM_message_encode(uint8_t *raw, const void *_nrecord, void *_ctx) +{ + H5SM_bt2_ctx_t *ctx = (H5SM_bt2_ctx_t *)_ctx; /* Callback context structure */ + const H5SM_sohm_t *message = (const H5SM_sohm_t *)_nrecord; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_encode) + + /* Sanity check */ + HDassert(ctx); + + *raw++ = message->location; + UINT32ENCODE(raw, message->hash); + + if(message->location == H5SM_IN_HEAP) { + UINT32ENCODE(raw, message->u.heap_loc.ref_count); + UINT64ENCODE(raw, message->u.heap_loc.fheap_id); + } /* end if */ + else { + HDassert(message->location == H5SM_IN_OH); + + *raw++ = 0; /* reserved (possible flags byte) */ + *raw++ = (uint8_t)message->msg_type_id; + UINT16ENCODE(raw, message->u.mesg_loc.index); + H5F_addr_encode_len(ctx->sizeof_addr, &raw, message->u.mesg_loc.oh_addr); + } /* end else */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_message_encode */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_message_decode + * + * Purpose: Read an encoded SOHM message from RAW into an H5SM_sohm_t struct. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5SM_message_decode(const uint8_t *raw, void *_nrecord, void *_ctx) +{ + H5SM_bt2_ctx_t *ctx = (H5SM_bt2_ctx_t *)_ctx; /* Callback context structure */ + H5SM_sohm_t *message = (H5SM_sohm_t *)_nrecord; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_decode) + + message->location = (H5SM_storage_loc_t)*raw++; + UINT32DECODE(raw, message->hash); + + if(message->location == H5SM_IN_HEAP) { + UINT32DECODE(raw, message->u.heap_loc.ref_count); + UINT64DECODE(raw, message->u.heap_loc.fheap_id); + } /* end if */ + else { + HDassert(message->location == H5SM_IN_OH); + + raw++; /* reserved */ + message->msg_type_id = *raw++; + UINT16DECODE(raw, message->u.mesg_loc.index); + H5F_addr_decode_len(ctx->sizeof_addr, &raw, &message->u.mesg_loc.oh_addr); + } /* end else */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_message_decode */ + |