/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Programmer: Robb Matzke * Wednesday, April 1, 1998 * * Purpose: Functions that operate on a shared message. The shared * message doesn't ever actually appear in the object header as * a normal message. Instead, if a message is shared, the * H5O_FLAG_SHARED bit is set and the message body is that * defined here for H5O_SHARED. The message ID is the ID of the * pointed-to message and the pointed-to message is stored in * the global heap. */ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ #define H5O_PACKAGE /*suppress error about including H5Opkg */ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ #include "H5Gprivate.h" /* Groups */ #include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ static void *H5O_shared_decode (H5F_t*, hid_t dxpl_id, const uint8_t*); static herr_t H5O_shared_encode (H5F_t*, uint8_t*, const void*); static void *H5O_shared_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_shared_size (const H5F_t*, const void *_mesg); static herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); static herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg); static herr_t H5O_shared_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type, void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *_udata); static void *H5O_shared_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); static herr_t H5O_shared_debug (H5F_t*, hid_t dxpl_id, const void*, FILE*, int, int); /* This message derives from H5O message class */ const H5O_msg_class_t H5O_MSG_SHARED[1] = {{ H5O_SHARED_ID, /*message id number */ "shared", /*message name for debugging */ sizeof(H5O_shared_t), /*native message size */ H5O_shared_decode, /*decode method */ H5O_shared_encode, /*encode method */ H5O_shared_copy, /*copy the native value */ H5O_shared_size, /*size method */ NULL, /*no reset method */ NULL, /*no free method */ H5O_shared_delete, /*file delete method */ H5O_shared_link, /*link method */ NULL, /*get share method */ NULL, /*set share method */ H5O_shared_pre_copy_file, /* pre copy native value to file */ H5O_shared_copy_file, /* copy native value to file */ NULL, /* post copy native value to file */ H5O_shared_debug /*debug method */ }}; /* Old version, with full symbol table entry as link for object header sharing */ #define H5O_SHARED_VERSION_1 1 /* New version, with just address of object as link for object header sharing */ #define H5O_SHARED_VERSION 2 /*------------------------------------------------------------------------- * Function: H5O_shared_read * * Purpose: Reads a message referred to by a shared message. * * Return: Success: Ptr to message in native format. The message * should be freed by calling H5O_reset(). If * MESG is a null pointer then the caller should * also call H5MM_xfree() on the return value * after calling H5O_reset(). * * Failure: NULL * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu * Sep 24 2003 * * Modifications: * *------------------------------------------------------------------------- */ void * H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_shared_t *shared, const H5O_msg_class_t *type, void *mesg) { void *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_shared_read) /* check args */ HDassert(f); HDassert(shared); HDassert(type); /* Get the shared message */ ret_value = H5O_read_real(&(shared->oloc), type, 0, mesg, dxpl_id); if(type->set_share && (type->set_share)(f, ret_value, shared) < 0) HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_shared_read() */ /*------------------------------------------------------------------------- * Function: H5O_shared_link_adj * * Purpose: Changes the link count for the object referenced by a shared * message. * * Return: Success: New link count * * Failure: Negative * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu * Sep 26 2003 * * Modifications: * *------------------------------------------------------------------------- */ static int H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared, int adjust) { int ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_shared_link_adj) /* check args */ HDassert(f); HDassert(shared); /* * The shared message is stored in some other object header. * The other object header must be in the same file as the * new object header. Adjust the reference count on that * object header. */ if(shared->oloc.file->shared != f->shared) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "interfile hard links are not allowed") if((ret_value = H5O_link(&(shared->oloc), adjust, dxpl_id)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_shared_link_adj() */ /*------------------------------------------------------------------------- * Function: H5O_shared_decode * * Purpose: Decodes a shared object message and returns it. * * Return: Success: Ptr to a new shared object message. * * Failure: NULL * * Programmer: Robb Matzke * Thursday, April 2, 1998 * * Modifications: * Robb Matzke, 1998-07-20 * Added a version number to the beginning of the message. *------------------------------------------------------------------------- */ static void * H5O_shared_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *buf) { H5O_shared_t *mesg = NULL; unsigned flags, version; void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_shared_decode) /* Check args */ HDassert(f); HDassert(buf); /* Decode */ if(NULL == (mesg = H5MM_calloc (sizeof(H5O_shared_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Version */ version = *buf++; if(version != H5O_SHARED_VERSION_1 && version != H5O_SHARED_VERSION) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for shared object message") /* Get the shared information flags */ flags = *buf++; /* Unused currently */ /* Skip reserved bytes (for version 1) */ if(version == H5O_SHARED_VERSION_1) buf += 6; /* Body */ if(version == H5O_SHARED_VERSION_1) H5G_obj_ent_decode(f, &buf, &(mesg->oloc)); else { HDassert(version == H5O_SHARED_VERSION); H5F_addr_decode(f, &buf, &(mesg->oloc.addr)); mesg->oloc.file = f; } /* end else */ /* Set return value */ ret_value = mesg; done: if(ret_value==NULL) { if(mesg!=NULL) H5MM_xfree(mesg); } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_shared_decode() */ /*------------------------------------------------------------------------- * Function: H5O_shared_encode * * Purpose: Encodes message _MESG into buffer BUF. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Thursday, April 2, 1998 * * Modifications: * Robb Matzke, 1998-07-20 * Added a version number to the beginning of the message. * *------------------------------------------------------------------------- */ static herr_t H5O_shared_encode (H5F_t *f, uint8_t *buf/*out*/, const void *_mesg) { const H5O_shared_t *mesg = (const H5O_shared_t *)_mesg; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_encode) /* Check args */ HDassert(f); HDassert(buf); HDassert(mesg); /* Encode */ *buf++ = H5O_SHARED_VERSION; *buf++ = 0; /* No flags currently */ H5F_addr_encode(f, &buf, mesg->oloc.addr); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_shared_encode() */ /*------------------------------------------------------------------------- * Function: H5O_shared_copy * * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if * necessary. * * Return: Success: Ptr to _DEST * * Failure: NULL * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu * Sep 26 2003 * * Modifications: * *------------------------------------------------------------------------- */ static void * H5O_shared_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags) { const H5O_shared_t *mesg = (const H5O_shared_t *) _mesg; H5O_shared_t *dest = (H5O_shared_t *) _dest; void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_shared_copy); /* check args */ assert(mesg); if (!dest && NULL==(dest = H5MM_malloc (sizeof(H5O_shared_t)))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* copy */ *dest = *mesg; /* Set return value */ ret_value=dest; done: FUNC_LEAVE_NOAPI(ret_value); } /* end H5O_shared_copy() */ /*------------------------------------------------------------------------- * Function: H5O_shared_size * * Purpose: Returns the length of a shared object message. * * Return: Success: Length * * Failure: 0 * * Programmer: Robb Matzke * Thursday, April 2, 1998 * *------------------------------------------------------------------------- */ static size_t H5O_shared_size (const H5F_t *f, const void UNUSED *_mesg) { size_t ret_value; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_size); ret_value = 1 + /*version */ 1 + /*the flags field */ H5F_SIZEOF_ADDR(f); /*sharing by another obj hdr */ FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- * Function: H5O_shared_delete * * Purpose: Free file space referenced by message * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Friday, September 26, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link) { const H5O_shared_t *shared = (const H5O_shared_t *) _mesg; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_shared_delete); /* check args */ assert(f); assert(shared); /* Decrement the reference count on the shared object, if requested */ if(adj_link) if(H5O_shared_link_adj(f, dxpl_id, shared, -1)<0) HGOTO_ERROR (H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count") done: FUNC_LEAVE_NOAPI(ret_value); } /* end H5O_shared_delete() */ /*------------------------------------------------------------------------- * Function: H5O_shared_link * * Purpose: Increment reference count on any objects referenced by * message * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Friday, September 26, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg) { const H5O_shared_t *shared = (const H5O_shared_t *) _mesg; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_shared_link); /* check args */ assert(f); assert(shared); /* Decrement the reference count on the shared object */ if(H5O_shared_link_adj(f,dxpl_id,shared,1)<0) HGOTO_ERROR (H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count"); done: FUNC_LEAVE_NOAPI(ret_value); } /* end H5O_shared_link() */ /*------------------------------------------------------------------------- * Function: H5O_shared_copy_file * * Purpose: Copies a message from _MESG to _DEST in file * * Return: Success: Ptr to _DEST * * Failure: NULL * * Programmer: Quincey Koziol * November 1, 2005 * *------------------------------------------------------------------------- */ static void * H5O_shared_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void UNUSED *udata) { H5O_shared_t *shared_src = (H5O_shared_t *)native_src; H5O_shared_t *shared_dst = NULL; void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_shared_copy_file) /* check args */ HDassert(shared_src); HDassert(file_dst); HDassert(cpy_info); /* Allocate space for the destination message */ if(NULL == (shared_dst = H5MM_malloc(sizeof(H5O_shared_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Reset group entry for new object */ H5O_loc_reset(&(shared_dst->oloc)); shared_dst->oloc.file = file_dst; /* Copy the shared object from source to destination */ if(H5O_copy_header_map(&(shared_src->oloc), &(shared_dst->oloc), dxpl_id, cpy_info, FALSE) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object") /* Set return value */ ret_value = shared_dst; done: if(!ret_value) if(shared_dst) H5MM_xfree(shared_dst); FUNC_LEAVE_NOAPI(ret_value) } /* H5O_shared_copy_file() */ /*------------------------------------------------------------------------- * Function: H5O_shared_pre_copy_file * * Purpose: Perform any necessary actions before copying message between * files for shared messages. * * Return: Success: Non-negative * * Failure: Negative * * Programmer: Peter Cao * Saturday, February 11, 2006 * *------------------------------------------------------------------------- */ static herr_t H5O_shared_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type, void *native_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata) { H5O_shared_t *shared_src = (H5O_shared_t *)native_src; void *mesg_native = NULL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_shared_pre_copy_file) /* check args */ HDassert(file_src); HDassert(type); if(type->pre_copy_file) { /* Go get the actual shared message */ if((mesg_native = H5O_read_real(&(shared_src->oloc), type, 0, NULL, H5AC_dxpl_id)) == NULL) HGOTO_ERROR(H5E_OHDR, H5E_READERROR, FAIL, "unable to load object header") /* Perform "pre copy" operation on messge */ if((type->pre_copy_file)(file_src, type, mesg_native, deleted, cpy_info, udata) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to perform 'pre copy' operation on message") } /* end of if */ done: if(mesg_native) H5O_free_real(type, mesg_native); FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_shared_pre_copy_file() */ /*------------------------------------------------------------------------- * Function: H5O_shared_debug * * Purpose: Prints debugging info for the message * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Thursday, April 2, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5O_shared_debug (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE *stream, int indent, int fwidth) { const H5O_shared_t *mesg = (const H5O_shared_t *)_mesg; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_debug) /* Check args */ HDassert(f); HDassert(mesg); HDassert(stream); HDassert(indent >= 0); HDassert(fwidth >= 0); HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Sharing method", "Obj Hdr"); HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, "Object address:", mesg->oloc.addr); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_shared_debug() */