/*------------------------------------------------------------------------- * Function: H5O_drvinfo_copy * * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if * necessary. * * Return: Success: Ptr to _DEST * Failure: NULL * * Programmer: Quincey Koziol * Mar 1, 2007 * *------------------------------------------------------------------------- */ static void * H5O_drvinfo_copy(const void *_mesg, void *_dest) { const H5O_drvinfo_t *mesg = (const H5O_drvinfo_t *)_mesg; H5O_drvinfo_t *dest = (H5O_drvinfo_t *)_dest; void *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(mesg); if(!dest && NULL == (dest = (H5O_drvinfo_t *)H5MM_malloc(sizeof(H5O_drvinfo_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for shared message table message") /* Shallow copy the fields */ *dest = *mesg; /* Copy the buffer */ if(NULL == (dest->buf = (uint8_t *)H5MM_malloc(mesg->len))) { if(dest != _dest) dest = (H5O_drvinfo_t *)H5MM_xfree(dest); HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") } /* end if */ HDmemcpy(dest->buf, mesg->buf, mesg->len); /* Set return value */ ret_value = dest; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_drvinfo_copy() */
/*-------------------------------------------------------------------------- * Function: H5L_build_name * * Purpose: Prepend PREFIX to FILE_NAME and store in FULL_NAME * * Return: Non-negative on success/Negative on failure * * Programmer: Vailin Choi, April 2, 2008 * * Modification: Raymond Lu, 14 Jan. 2009 * Added support for OpenVMS pathname --------------------------------------------------------------------------*/ static herr_t H5L_build_name(char *prefix, char *file_name, char **full_name/*out*/) { size_t prefix_len; /* length of prefix */ size_t fname_len; /* Length of external link file name */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5L_build_name) prefix_len = HDstrlen(prefix); fname_len = HDstrlen(file_name); /* Allocate a buffer to hold the filename + prefix + possibly the delimiter + terminating null byte */ if(NULL == (*full_name = (char *)H5MM_malloc(prefix_len + fname_len + 2))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer") /* Copy the prefix into the buffer */ HDstrcpy(*full_name, prefix); if (!CHECK_DELIMITER(prefix[prefix_len-1])) HDstrcat(*full_name, DIR_SEPS); /* Add the external link's filename to the prefix supplied */ HDstrcat(*full_name, file_name); done: FUNC_LEAVE_NOAPI(ret_value) } /* H5L_build_name() */
/*------------------------------------------------------------------------- * Function: H5O_fill_decode * * Purpose: Decode a fill value message. * * Return: Success: Ptr to new message in native struct. * * Failure: NULL * * Programmer: Robb Matzke * Wednesday, September 30, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static void * H5O_fill_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5O_fill_t *mesg=NULL; void *ret_value; FUNC_ENTER_NOAPI_NOINIT(H5O_fill_decode); assert(f); assert(p); if (NULL==(mesg=H5FL_CALLOC(H5O_fill_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value message"); UINT32DECODE(p, mesg->size); if (mesg->size>0) { if (NULL==(mesg->buf=H5MM_malloc(mesg->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value"); HDmemcpy(mesg->buf, p, mesg->size); } /* Set return value */ ret_value = (void*)mesg; done: if (!ret_value && mesg) { if(mesg->buf) H5MM_xfree(mesg->buf); H5FL_FREE(H5O_fill_t,mesg); } FUNC_LEAVE_NOAPI(ret_value); }
/*------------------------------------------------------------------------- * Function: H5O_name_decode * * Purpose: Decode a name message and return a pointer to a new * native message struct. * * Return: Success: Ptr to new message in native struct. * * Failure: NULL * * Programmer: Robb Matzke * [email protected] * Aug 12 1997 * *------------------------------------------------------------------------- */ static void * H5O_name_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, H5O_t UNUSED *open_oh, unsigned UNUSED mesg_flags, unsigned UNUSED *ioflags, const uint8_t *p) { H5O_name_t *mesg; void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* check args */ HDassert(f); HDassert(p); /* decode */ if(NULL == (mesg = (H5O_name_t *)H5MM_calloc(sizeof(H5O_name_t))) || NULL == (mesg->s = (char *)H5MM_malloc(HDstrlen((const char *)p) + 1))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") HDstrcpy(mesg->s, (const char *)p); /* Set return value */ ret_value = mesg; done: if(NULL == ret_value) { if(mesg) mesg = (H5O_name_t *)H5MM_xfree(mesg); } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_name_decode() */
/*------------------------------------------------------------------------- * Function: H5MM_realloc * * Purpose: Just like the POSIX version of realloc(3). Specifically, the * following calls are equivalent * * H5MM_realloc (NULL, size) <==> H5MM_malloc (size) * H5MM_realloc (ptr, 0) <==> H5MM_xfree (ptr) * H5MM_realloc (NULL, 0) <==> NULL * * Return: Success: Ptr to new memory or NULL if the memory * was freed. * * Failure: abort() * * Programmer: Robb Matzke * [email protected] * Jul 10 1997 * * Modifications: * *------------------------------------------------------------------------- */ void * H5MM_realloc(void *mem, size_t size) { void *ret_value; /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MM_realloc); if (!mem) { if (0 == size) HGOTO_DONE(NULL); mem = H5MM_malloc(size); } else if (0 == size) { mem = H5MM_xfree(mem); } else { mem = HDrealloc(mem, size); assert(mem); } /* Set return value */ ret_value=mem; done: FUNC_LEAVE_NOAPI(ret_value); }
/*------------------------------------------------------------------------- * Function: H5MP_new_page * * Purpose: Allocate new page for a memory pool * * Return: Pointer to the page allocated on success/NULL on failure * * Programmer: Quincey Koziol * [email protected] * May 4 2005 * *------------------------------------------------------------------------- */ static H5MP_page_t * H5MP_new_page(H5MP_pool_t *mp, size_t page_size) { H5MP_page_t *new_page; /* New page created */ H5MP_page_blk_t *first_blk; /* Pointer to first block in page */ H5MP_page_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5MP_new_page) /* Sanity check */ HDassert(mp); HDassert(page_size >= mp->page_size); /* Allocate page */ if(page_size > mp->page_size) { if(NULL == (new_page = H5MM_malloc(page_size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page") new_page->free_size = page_size - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t)); new_page->fac_alloc = FALSE; } /* end if */ else { if((new_page = H5FL_FAC_MALLOC(mp->page_fac)) == NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page") new_page->free_size = mp->max_size; new_page->fac_alloc = TRUE; } /* end else */ #ifdef QAK HDfprintf(stderr,"%s: Allocating new page = %p\n", FUNC, new_page); #endif /* QAK */ /* Initialize page information */ first_blk = H5MP_PAGE_FIRST_BLOCK(new_page); first_blk->size = new_page->free_size; first_blk->page = new_page; first_blk->is_free = TRUE; first_blk->prev = NULL; first_blk->next = NULL; /* Insert into page list */ new_page->prev = NULL; new_page->next = mp->first; if(mp->first) mp->first->prev = new_page; mp->first = new_page; /* Account for new free space */ new_page->free_blk = first_blk; mp->free_size += new_page->free_size; /* Assign return value */ ret_value = new_page; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5MP_new_page() */
/*------------------------------------------------------------------------- * Function: H5O_fill_new_decode * * Purpose: Decode a new fill value message. The new fill value * message is fill value plus space allocation time and * fill value writing time and whether fill value is defined. * * Return: Success: Ptr to new message in native struct. * * Failure: NULL * * Programmer: Raymond Lu * Feb 26, 2002 * * Modifications: * *------------------------------------------------------------------------- */ static void * H5O_fill_new_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5O_fill_new_t *mesg=NULL; int version; void *ret_value; FUNC_ENTER_NOAPI_NOINIT(H5O_fill_new_decode); assert(f); assert(p); if (NULL==(mesg=H5FL_CALLOC(H5O_fill_new_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value message"); /* Version */ version = *p++; if( version != H5O_FILL_VERSION && version !=H5O_FILL_VERSION_2) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for fill value message"); /* Space allocation time */ mesg->alloc_time = (H5D_alloc_time_t)*p++; /* Fill value write time */ mesg->fill_time = (H5D_fill_time_t)*p++; /* Whether fill value is defined */ mesg->fill_defined = *p++; /* Only decode fill value information if one is defined */ if(mesg->fill_defined) { INT32DECODE(p, mesg->size); if (mesg->size>0) { H5_CHECK_OVERFLOW(mesg->size,ssize_t,size_t); if (NULL==(mesg->buf=H5MM_malloc((size_t)mesg->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value"); HDmemcpy(mesg->buf, p, (size_t)mesg->size); } } /* end if */ else mesg->size=(-1); /* Set return value */ ret_value = (void*)mesg; done: if (!ret_value && mesg) { if(mesg->buf) H5MM_xfree(mesg->buf); H5FL_FREE(H5O_fill_new_t,mesg); } FUNC_LEAVE_NOAPI(ret_value); }
/*------------------------------------------------------------------------- * Function: H5O_fill_copy_dyn * * Purpose: Copy dynamic fill value fields * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Thursday, May 31, 2007 * *------------------------------------------------------------------------- */ static herr_t H5O_fill_copy_dyn(H5O_fill_t *dest, const H5O_fill_t *mesg) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_fill_copy_dyn) HDassert(dest); HDassert(mesg); /* Copy data type of fill value */ if(mesg->type) { if(NULL == (dest->type = H5T_copy(mesg->type, H5T_COPY_TRANSIENT))) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy fill value data type"); } /* end if */ else dest->type = NULL; /* Copy fill value and its size */ if(mesg->buf) { H5_CHECK_OVERFLOW(mesg->size,ssize_t,size_t); if(NULL == (dest->buf = H5MM_malloc((size_t)mesg->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill value"); HDmemcpy(dest->buf, mesg->buf, (size_t)mesg->size); /* Check for needing to convert/copy fill value */ if(mesg->type) { H5T_path_t *tpath; /* Conversion information */ /* Set up type conversion function */ if(NULL == (tpath = H5T_path_find(mesg->type, dest->type, NULL, NULL, H5AC_ind_dxpl_id))) HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types") /* If necessary, convert fill value datatypes (which copies VL components, etc.) */ if(!H5T_path_noop(tpath)) { hid_t dst_id, src_id; /* Source & destination datatypes for type conversion */ uint8_t *bkg_buf = NULL; /* Background conversion buffer */ size_t bkg_size; /* Size of background buffer */ /* Wrap copies of types to convert */ dst_id = H5I_register(H5I_DATATYPE, H5T_copy(dest->type, H5T_COPY_TRANSIENT)); if(dst_id < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype") src_id = H5I_register(H5I_DATATYPE, H5T_copy(mesg->type, H5T_COPY_ALL)); if(src_id < 0) { H5I_dec_ref(dst_id); HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype") } /* end if */
/*------------------------------------------------------------------------- * Function: H5MM_strdup * * Purpose: Duplicates a string. If the string to be duplicated is the * null pointer, then return null. If the string to be duplicated * is the empty string then return a new empty string. * * Return: Success: Ptr to a new string (or null if no string). * * Failure: abort() * * Programmer: Robb Matzke * [email protected] * Jul 10 1997 * * Modifications: * *------------------------------------------------------------------------- */ char * H5MM_strdup(const char *s) { char *ret_value; FUNC_ENTER_NOAPI(H5MM_strdup, NULL) if(!s) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "null string") if(NULL == (ret_value = (char *)H5MM_malloc(HDstrlen(s) + 1))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") HDstrcpy(ret_value, s); done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5MM_strdup() */
/*------------------------------------------------------------------------- * Function: H5MM_xstrdup * * Purpose: Duplicates a string. If the string to be duplicated is the * null pointer, then return null. If the string to be duplicated * is the empty string then return a new empty string. * * Return: Success: Ptr to a new string (or null if no string). * * Failure: abort() * * Programmer: Robb Matzke * [email protected] * Jul 10 1997 * *------------------------------------------------------------------------- */ char * H5MM_xstrdup(const char *s) { char *ret_value = NULL; /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MM_xstrdup) if(s) { ret_value = (char *)H5MM_malloc(HDstrlen(s) + 1); HDassert(ret_value); HDstrcpy(ret_value, s); } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5MM_xstrdup() */
/*------------------------------------------------------------------------- * Function: H5O_efl_copy * * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if * necessary. * * Return: Success: Ptr to _DEST * * Failure: NULL * * Programmer: Robb Matzke * Tuesday, November 25, 1997 * *------------------------------------------------------------------------- */ static void * H5O_efl_copy(const void *_mesg, void *_dest) { const H5O_efl_t *mesg = (const H5O_efl_t *) _mesg; H5O_efl_t *dest = (H5O_efl_t *) _dest; size_t u; /* Local index variable */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_efl_copy) /* check args */ HDassert(mesg); if(!dest) { if(NULL == (dest = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t))) || NULL == (dest->slot = (H5O_efl_entry_t *)H5MM_malloc(mesg->nalloc * sizeof(H5O_efl_entry_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") } else if(dest->nalloc < mesg->nalloc) {
/*------------------------------------------------------------------------- * Function: H5O_layout_copy * * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if * necessary. * * Return: Success: Ptr to _DEST * * Failure: NULL * * Programmer: Robb Matzke * Wednesday, October 8, 1997 * *------------------------------------------------------------------------- */ static void * H5O_layout_copy(const void *_mesg, void *_dest) { const H5O_layout_t *mesg = (const H5O_layout_t *) _mesg; H5O_layout_t *dest = (H5O_layout_t *) _dest; void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_layout_copy) /* check args */ HDassert(mesg); /* Allocate destination message, if necessary */ if(!dest && NULL == (dest = H5FL_MALLOC(H5O_layout_t))) HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "layout message allocation failed") /* copy */ *dest = *mesg; /* Deep copy the buffer for compact datasets also */ if(mesg->type == H5D_COMPACT && mesg->storage.u.compact.size > 0) { /* Allocate memory for the raw data */ if(NULL == (dest->storage.u.compact.buf = H5MM_malloc(dest->storage.u.compact.size))) HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "unable to allocate memory for compact dataset") /* Copy over the raw data */ HDmemcpy(dest->storage.u.compact.buf, mesg->storage.u.compact.buf, dest->storage.u.compact.size); } /* end if */ /* Reset the pointer of the chunked storage index but not the address */ if(dest->type == H5D_CHUNKED && dest->storage.u.chunk.ops) H5D_chunk_idx_reset(&dest->storage.u.chunk, FALSE); /* Set return value */ ret_value = dest; done: if(ret_value == NULL) if(NULL == _dest) dest = H5FL_FREE(H5O_layout_t, dest); FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_layout_copy() */
/*------------------------------------------------------------------------- * Function: H5MM_xstrdup * * Purpose: Duplicates a string. If the string to be duplicated is the * null pointer, then return null. If the string to be duplicated * is the empty string then return a new empty string. * * Return: Success: Ptr to a new string (or null if no string). * * Failure: abort() * * Programmer: Robb Matzke * [email protected] * Jul 10 1997 * * Modifications: * *------------------------------------------------------------------------- */ char * H5MM_xstrdup(const char *s) { char *ret_value=NULL; /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MM_xstrdup); if (s) { ret_value = H5MM_malloc(HDstrlen(s) + 1); assert (ret_value); HDstrcpy(ret_value, s); } /* end if */ #ifdef LATER done: #endif /* LATER */ FUNC_LEAVE_NOAPI(ret_value); }
/*------------------------------------------------------------------------- * Function: H5G_compact_build_table * * Purpose: Builds a table containing a sorted (alphabetically) list of * links for a group * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Sep 6, 2005 * *------------------------------------------------------------------------- */ static herr_t H5G_compact_build_table(const H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, H5G_link_table_t *ltable) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5G_compact_build_table) /* Sanity check */ HDassert(oloc); HDassert(linfo); HDassert(ltable); /* Set size of table */ H5_CHECK_OVERFLOW(linfo->nlinks, hsize_t, size_t); ltable->nlinks = (size_t)linfo->nlinks; /* Allocate space for the table entries */ if(ltable->nlinks > 0) { H5G_iter_bt_t udata; /* User data for iteration callback */ H5O_mesg_operator_t op; /* Message operator */ /* Allocate the link table */ if((ltable->lnks = (H5O_link_t *)H5MM_malloc(sizeof(H5O_link_t) * ltable->nlinks)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Set up user data for iteration */ udata.ltable = ltable; udata.curr_lnk = 0; /* Iterate through the link messages, adding them to the table */ op.op_type = H5O_MESG_OP_APP; op.u.app_op = H5G_compact_build_table_cb; if(H5O_msg_iterate(oloc, H5O_LINK_ID, &op, &udata, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over link messages") /* Sort link table in correct iteration order */ if(H5G_link_sort_table(ltable, idx_type, order) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTSORT, FAIL, "error sorting link messages") } /* end if */
/*------------------------------------------------------------------------- * Function: H5F_cwfs_add * * Purpose: Add a global heap collection to the CWFS for a file. * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * Tuesday, July 19, 2011 * *------------------------------------------------------------------------- */ herr_t H5F_cwfs_add(H5F_t *f, H5HG_heap_t *heap) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Check args */ HDassert(f); HDassert(f->shared); HDassert(heap); /* * Add the new heap to the CWFS list, removing some other entry if * necessary to make room. We remove the right-most entry that has less * free space than this heap. */ if(NULL == f->shared->cwfs) { if(NULL == (f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5F_NCWFS * sizeof(H5HG_heap_t *)))) HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate CWFS for file") f->shared->cwfs[0] = heap; f->shared->ncwfs = 1; } else if(H5F_NCWFS == f->shared->ncwfs) { int i; /* Local index variable */ for(i = H5F_NCWFS - 1; i >= 0; --i) if(H5HG_FREE_SIZE(f->shared->cwfs[i]) < H5HG_FREE_SIZE(heap)) { HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, (size_t)i * sizeof(H5HG_heap_t *)); f->shared->cwfs[0] = heap; break; } /* end if */ } else { HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, f->shared->ncwfs * sizeof(H5HG_heap_t *)); f->shared->cwfs[0] = heap; f->shared->ncwfs += 1; } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5F_cwfs_add() */
/*-------------------------------------------------------------------------- * Function: H5L_build_name * * Purpose: Prepend PREFIX to FILE_NAME and store in FULL_NAME * * Return: Non-negative on success/Negative on failure * * Programmer: Vailin Choi, April 2, 2008 * * Modification: Raymond Lu, 14 Jan. 2009 * Added support for OpenVMS pathname --------------------------------------------------------------------------*/ static herr_t H5L_build_name(char *prefix, char *file_name, char **full_name/*out*/) { size_t prefix_len; /* length of prefix */ size_t fname_len; /* Length of external link file name */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT prefix_len = HDstrlen(prefix); fname_len = HDstrlen(file_name); /* Allocate a buffer to hold the filename + prefix + possibly the delimiter + terminating null byte */ if(NULL == (*full_name = (char *)H5MM_malloc(prefix_len + fname_len + 2))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer") /* Compose the full file name */ HDsnprintf(*full_name, (prefix_len + fname_len + 2), "%s%s%s", prefix, (H5_CHECK_DELIMITER(prefix[prefix_len - 1]) ? "" : H5_DIR_SEPS), file_name); done: FUNC_LEAVE_NOAPI(ret_value) } /* H5L_build_name() */
/*------------------------------------------------------------------------- * Function: H5O_drvinfo_decode * * Purpose: Decode a shared message table message and return a pointer * to a newly allocated H5O_drvinfo_t struct. * * Return: Success: Ptr to new message in native struct. * Failure: NULL * * Programmer: Quincey Koziol * Mar 1, 2007 * *------------------------------------------------------------------------- */ static void * H5O_drvinfo_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, size_t H5_ATTR_UNUSED p_size, const uint8_t *p) { H5O_drvinfo_t *mesg; /* Native message */ void *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(f); HDassert(p); /* Version of message */ if(*p++ != H5O_DRVINFO_VERSION) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message") /* Allocate space for message */ if(NULL == (mesg = (H5O_drvinfo_t *)H5MM_calloc(sizeof(H5O_drvinfo_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for driver info message") /* Retrieve driver name */ HDmemcpy(mesg->name, p, 8); mesg->name[8] = '\0'; p += 8; /* Decode buffer size */ UINT16DECODE(p, mesg->len); HDassert(mesg->len); /* Allocate space for buffer */ if(NULL == (mesg->buf = (uint8_t *)H5MM_malloc(mesg->len))) { mesg = (H5O_drvinfo_t *)H5MM_xfree(mesg); HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for driver info buffer") } /* end if */
/*------------------------------------------------------------------------- * Function: H5O_shmesg_copy * * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if * necessary. * * Return: Success: Ptr to _DEST * Failure: NULL * * Programmer: James Laird * Jan 29, 2007 * *------------------------------------------------------------------------- */ static void * H5O_shmesg_copy(const void *_mesg, void *_dest) { const H5O_shmesg_table_t *mesg = (const H5O_shmesg_table_t *)_mesg; H5O_shmesg_table_t *dest = (H5O_shmesg_table_t *)_dest; void *ret_value; FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(mesg); if(!dest && NULL == (dest = (H5O_shmesg_table_t *)H5MM_malloc(sizeof(H5O_shmesg_table_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for shared message table message") /* All this message requires is a shallow copy */ *dest = *mesg; /* Set return value */ ret_value = dest; done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_shmesg_copy() */
/*------------------------------------------------------------------------- * Function: H5MM_realloc * * Purpose: Just like the POSIX version of realloc(3). Specifically, the * following calls are equivalent * * H5MM_realloc (NULL, size) <==> H5MM_malloc (size) * H5MM_realloc (ptr, 0) <==> H5MM_xfree (ptr) * H5MM_realloc (NULL, 0) <==> NULL * * Return: Success: Ptr to new memory or NULL if the memory * was freed. * * Failure: NULL * * Programmer: Robb Matzke * [email protected] * Jul 10 1997 * *------------------------------------------------------------------------- */ void * H5MM_realloc(void *mem, size_t size) { void *ret_value; /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MM_realloc) if(NULL == mem) { if(0 == size) mem = NULL; else mem = H5MM_malloc(size); } /* end if */ else if(0 == size) mem = H5MM_xfree(mem); else mem = HDrealloc(mem, size); /* Set return value */ ret_value = mem; FUNC_LEAVE_NOAPI(ret_value) } /* end H5MM_realloc() */
/*------------------------------------------------------------------------- * Function: H5Z_filter_deflate * * Purpose: Implement an I/O filter around the 'deflate' algorithm in * libz * * Return: Success: Size of buffer filtered * Failure: 0 * * Programmer: Robb Matzke * Thursday, April 16, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static size_t H5Z_filter_deflate (unsigned flags, size_t cd_nelmts, const unsigned cd_values[], size_t nbytes, size_t *buf_size, void **buf) { void *outbuf = NULL; /* Pointer to new buffer */ int status; /* Status from zlib operation */ size_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5Z_filter_deflate, 0) /* Check arguments */ if (cd_nelmts!=1 || cd_values[0]>9) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid deflate aggression level") if (flags & H5Z_FLAG_REVERSE) { /* Input; uncompress */ z_stream z_strm; /* zlib parameters */ size_t nalloc = *buf_size; /* Number of bytes for output (compressed) buffer */ /* Allocate space for the compressed buffer */ if (NULL==(outbuf = H5MM_malloc(nalloc))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed for deflate uncompression") /* Set the uncompression parameters */ HDmemset(&z_strm, 0, sizeof(z_strm)); z_strm.next_in = *buf; H5_ASSIGN_OVERFLOW(z_strm.avail_in,nbytes,size_t,uInt); z_strm.next_out = outbuf; H5_ASSIGN_OVERFLOW(z_strm.avail_out,nalloc,size_t,uInt); /* Initialize the uncompression routines */ if (Z_OK!=inflateInit(&z_strm)) HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, 0, "inflateInit() failed") /* Loop to uncompress the buffer */ do { /* Uncompress some data */ status = inflate(&z_strm, Z_SYNC_FLUSH); /* Check if we are done uncompressing data */ if (Z_STREAM_END==status) break; /*done*/ /* Check for error */ if (Z_OK!=status) { (void)inflateEnd(&z_strm); HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, 0, "inflate() failed") } else { /* If we're not done and just ran out of buffer space, get more */ if (0==z_strm.avail_out) { /* Allocate a buffer twice as big */ nalloc *= 2; if (NULL==(outbuf = H5MM_realloc(outbuf, nalloc))) { (void)inflateEnd(&z_strm); HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed for deflate uncompression") } /* Update pointers to buffer for next set of uncompressed data */ z_strm.next_out = (unsigned char*)outbuf + z_strm.total_out; z_strm.avail_out = (uInt)(nalloc - z_strm.total_out); }
/*------------------------------------------------------------------------- * Function: H5B2__insert_leaf * * Purpose: Adds a new record to a B-tree leaf node. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Mar 3 2005 * *------------------------------------------------------------------------- */ herr_t H5B2__insert_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, void *parent, void *udata) { H5B2_leaf_t *leaf; /* Pointer to leaf node */ unsigned leaf_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting the leaf node */ int cmp; /* Comparison value of records */ unsigned idx = 0; /* Location of record which matches key */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Check arguments. */ HDassert(hdr); HDassert(curr_node_ptr); HDassert(H5F_addr_defined(curr_node_ptr->addr)); /* Lock current B-tree node */ if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, parent, curr_node_ptr, FALSE, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node") /* Must have a leaf node with enough space to insert a record now */ HDassert(curr_node_ptr->node_nrec < hdr->node_info[0].max_nrec); /* Sanity check number of records */ HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec); HDassert(leaf->nrec == curr_node_ptr->node_nrec); /* Check for inserting into empty leaf */ if(leaf->nrec == 0) idx = 0; else { /* Find correct location to insert this record */ if(H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx, &cmp) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records") if(cmp == 0) HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree") if(cmp > 0) idx++; /* Make room for new record */ if(idx < leaf->nrec) HDmemmove(H5B2_LEAF_NREC(leaf, hdr, idx + 1), H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size * (leaf->nrec - idx)); } /* end else */ /* Make callback to store record in native form */ if((hdr->cls->store)(H5B2_LEAF_NREC(leaf, hdr, idx), udata) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node") /* Mark the node as dirty */ leaf_flags |= H5AC__DIRTIED_FLAG; /* Update record count for node pointer to current node */ curr_node_ptr->all_nrec++; curr_node_ptr->node_nrec++; /* Update record count for current node */ leaf->nrec++; /* Check for new record being the min or max for the tree */ /* (Don't use 'else' for the idx check, to allow for root leaf node) */ if(H5B2_POS_MIDDLE != curr_pos) { if(idx == 0) { if(H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) { if(hdr->min_native_rec == NULL) if(NULL == (hdr->min_native_rec = H5MM_malloc(hdr->cls->nrec_size))) HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree min record info") HDmemcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); } /* end if */ } /* end if */ if(idx == (unsigned)(leaf->nrec - 1)) { if(H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) { if(hdr->max_native_rec == NULL) if(NULL == (hdr->max_native_rec = H5MM_malloc(hdr->cls->nrec_size))) HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "memory allocation failed for v2 B-tree max record info") HDmemcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size); } /* end if */ } /* end if */ } /* end if */ done: /* Release the B-tree leaf node (marked as dirty) */ if(leaf) { /* Shadow the node if doing SWMR writes */ if(hdr->swmr_write && (leaf_flags & H5AC__DIRTIED_FLAG)) if(H5B2__shadow_leaf(leaf, dxpl_id, curr_node_ptr) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf B-tree node") /* Unprotect leaf node */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, leaf_flags) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node") } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* H5B2__insert_leaf() */
/*------------------------------------------------------------------------- * Function: H5O_layout_decode * * Purpose: Decode an data layout message and return a pointer to a * new one created with malloc(). * * Return: Success: Ptr to new message in native order. * * Failure: NULL * * Programmer: Robb Matzke * Wednesday, October 8, 1997 * *------------------------------------------------------------------------- */ static void * H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, H5O_t UNUSED *open_oh, unsigned UNUSED mesg_flags, unsigned UNUSED *ioflags, const uint8_t *p) { H5O_layout_t *mesg = NULL; unsigned u; void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_layout_decode) /* check args */ HDassert(f); HDassert(p); /* decode */ if(NULL == (mesg = H5FL_CALLOC(H5O_layout_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") mesg->version = *p++; if(mesg->version < H5O_LAYOUT_VERSION_1 || mesg->version > H5O_LAYOUT_VERSION_3) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for layout message") if(mesg->version < H5O_LAYOUT_VERSION_3) { unsigned ndims; /* Num dimensions in chunk */ /* Dimensionality */ ndims = *p++; if(ndims > H5O_LAYOUT_NDIMS) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "dimensionality is too large") /* Layout class */ mesg->type = (H5D_layout_t)*p++; assert(H5D_CONTIGUOUS == mesg->type || H5D_CHUNKED == mesg->type || H5D_COMPACT == mesg->type); /* Reserved bytes */ p += 5; /* Address */ if(mesg->type == H5D_CONTIGUOUS) { H5F_addr_decode(f, &p, &(mesg->storage.u.contig.addr)); /* Set the layout operations */ mesg->ops = H5D_LOPS_CONTIG; } /* end if */ else if(mesg->type == H5D_CHUNKED) { H5F_addr_decode(f, &p, &(mesg->storage.u.chunk.idx_addr)); /* Set the layout operations */ mesg->ops = H5D_LOPS_CHUNK; /* Set the chunk operations */ /* (Only "btree" indexing type currently supported in this version) */ mesg->storage.u.chunk.idx_type = H5D_CHUNK_BTREE; mesg->storage.u.chunk.ops = H5D_COPS_BTREE; } /* end if */ else { /* Sanity check */ HDassert(mesg->type == H5D_COMPACT); /* Set the layout operations */ mesg->ops = H5D_LOPS_COMPACT; } /* end else */ /* Read the size */ if(mesg->type != H5D_CHUNKED) { /* Don't compute size of contiguous storage here, due to possible * truncation of the dimension sizes when they were stored in this * version of the layout message. Compute the contiguous storage * size in the dataset code, where we've got the dataspace * information available also. - QAK 5/26/04 */ p += ndims * 4; /* Skip over dimension sizes (32-bit quantities) */ } /* end if */ else { mesg->u.chunk.ndims=ndims; for(u = 0; u < ndims; u++) UINT32DECODE(p, mesg->u.chunk.dim[u]); /* Compute chunk size */ for(u = 1, mesg->u.chunk.size = mesg->u.chunk.dim[0]; u < ndims; u++) mesg->u.chunk.size *= mesg->u.chunk.dim[u]; } /* end if */ if(mesg->type == H5D_COMPACT) { UINT32DECODE(p, mesg->storage.u.compact.size); if(mesg->storage.u.compact.size > 0) { if(NULL == (mesg->storage.u.compact.buf = H5MM_malloc(mesg->storage.u.compact.size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for compact data buffer") HDmemcpy(mesg->storage.u.compact.buf, p, mesg->storage.u.compact.size); p += mesg->storage.u.compact.size; } /* end if */ } /* end if */ } /* end if */ else { /* Layout class */ mesg->type = (H5D_layout_t)*p++; /* Interpret the rest of the message according to the layout class */ switch(mesg->type) { case H5D_COMPACT: UINT16DECODE(p, mesg->storage.u.compact.size); if(mesg->storage.u.compact.size > 0) { if(NULL == (mesg->storage.u.compact.buf = H5MM_malloc(mesg->storage.u.compact.size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for compact data buffer") HDmemcpy(mesg->storage.u.compact.buf, p, mesg->storage.u.compact.size); p += mesg->storage.u.compact.size; } /* end if */ /* Set the layout operations */ mesg->ops = H5D_LOPS_COMPACT; break; case H5D_CONTIGUOUS: H5F_addr_decode(f, &p, &(mesg->storage.u.contig.addr)); H5F_DECODE_LENGTH(f, p, mesg->storage.u.contig.size); /* Set the layout operations */ mesg->ops = H5D_LOPS_CONTIG; break; case H5D_CHUNKED: /* Dimensionality */ mesg->u.chunk.ndims = *p++; if(mesg->u.chunk.ndims > H5O_LAYOUT_NDIMS) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "dimensionality is too large") /* B-tree address */ H5F_addr_decode(f, &p, &(mesg->storage.u.chunk.idx_addr)); /* Chunk dimensions */ for(u = 0; u < mesg->u.chunk.ndims; u++) UINT32DECODE(p, mesg->u.chunk.dim[u]); /* Compute chunk size */ for(u = 1, mesg->u.chunk.size = mesg->u.chunk.dim[0]; u < mesg->u.chunk.ndims; u++) mesg->u.chunk.size *= mesg->u.chunk.dim[u]; /* Set the chunk operations */ /* (Only "btree" indexing type supported with v3 of message format) */ mesg->storage.u.chunk.idx_type = H5D_CHUNK_BTREE; mesg->storage.u.chunk.ops = H5D_COPS_BTREE; /* Set the layout operations */ mesg->ops = H5D_LOPS_CHUNK; break; default: HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "Invalid layout class") } /* end switch */ } /* end else */ /* Set return value */ ret_value = mesg; done: if(ret_value == NULL) if(mesg) mesg = H5FL_FREE(H5O_layout_t, mesg); FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_layout_decode() */
/*------------------------------------------------------------------------- * Function: H5O_layout_decode * * Purpose: Decode an data layout message and return a pointer to a * new one created with malloc(). * * Return: Success: Ptr to new message in native order. * * Failure: NULL * * Programmer: Robb Matzke * Wednesday, October 8, 1997 * * Modifications: * Robb Matzke, 1998-07-20 * Rearranged the message to add a version number at the beginning. * * Raymond Lu, 2002-2-26 * Added version number 2 case depends on if space has been allocated * at the moment when layout header message is updated. * *------------------------------------------------------------------------- */ static void * H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5O_layout_t *mesg = NULL; unsigned u; void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_layout_decode); /* check args */ assert(f); assert(p); /* decode */ if (NULL==(mesg = H5FL_CALLOC(H5O_layout_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Version. 1 when space allocated; 2 when space allocation is delayed */ mesg->version = *p++; if (mesg->version<H5O_LAYOUT_VERSION_1 || mesg->version>H5O_LAYOUT_VERSION_3) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for layout message"); if(mesg->version < H5O_LAYOUT_VERSION_3) { unsigned ndims; /* Num dimensions in chunk */ /* Dimensionality */ ndims = *p++; if (ndims>H5O_LAYOUT_NDIMS) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "dimensionality is too large"); /* Layout class */ mesg->type = (H5D_layout_t)*p++; assert(H5D_CONTIGUOUS == mesg->type || H5D_CHUNKED == mesg->type || H5D_COMPACT == mesg->type); /* Reserved bytes */ p += 5; /* Address */ if(mesg->type==H5D_CONTIGUOUS) H5F_addr_decode(f, &p, &(mesg->u.contig.addr)); else if(mesg->type==H5D_CHUNKED) H5F_addr_decode(f, &p, &(mesg->u.chunk.addr)); /* Read the size */ if(mesg->type!=H5D_CHUNKED) { mesg->unused.ndims=ndims; for (u = 0; u < ndims; u++) UINT32DECODE(p, mesg->unused.dim[u]); /* Don't compute size of contiguous storage here, due to possible * truncation of the dimension sizes when they were stored in this * version of the layout message. Compute the contiguous storage * size in the dataset code, where we've got the dataspace * information available also. - QAK 5/26/04 */ } /* end if */ else { mesg->u.chunk.ndims=ndims; for (u = 0; u < ndims; u++) UINT32DECODE(p, mesg->u.chunk.dim[u]); /* Compute chunk size */ for (u=1, mesg->u.chunk.size=mesg->u.chunk.dim[0]; u<ndims; u++) mesg->u.chunk.size *= mesg->u.chunk.dim[u]; } /* end if */ if(mesg->type == H5D_COMPACT) { UINT32DECODE(p, mesg->u.compact.size); if(mesg->u.compact.size > 0) { if(NULL==(mesg->u.compact.buf=H5MM_malloc(mesg->u.compact.size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for compact data buffer"); HDmemcpy(mesg->u.compact.buf, p, mesg->u.compact.size); p += mesg->u.compact.size; } } } /* end if */ else { /* Layout class */ mesg->type = (H5D_layout_t)*p++; /* Interpret the rest of the message according to the layout class */ switch(mesg->type) { case H5D_CONTIGUOUS: H5F_addr_decode(f, &p, &(mesg->u.contig.addr)); H5F_DECODE_LENGTH(f, p, mesg->u.contig.size); break; case H5D_CHUNKED: /* Dimensionality */ mesg->u.chunk.ndims = *p++; if (mesg->u.chunk.ndims>H5O_LAYOUT_NDIMS) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "dimensionality is too large"); /* B-tree address */ H5F_addr_decode(f, &p, &(mesg->u.chunk.addr)); /* Chunk dimensions */ for (u = 0; u < mesg->u.chunk.ndims; u++) UINT32DECODE(p, mesg->u.chunk.dim[u]); /* Compute chunk size */ for (u=1, mesg->u.chunk.size=mesg->u.chunk.dim[0]; u<mesg->u.chunk.ndims; u++) mesg->u.chunk.size *= mesg->u.chunk.dim[u]; break; case H5D_COMPACT: UINT16DECODE(p, mesg->u.compact.size); if(mesg->u.compact.size > 0) { if(NULL==(mesg->u.compact.buf=H5MM_malloc(mesg->u.compact.size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for compact data buffer"); HDmemcpy(mesg->u.compact.buf, p, mesg->u.compact.size); p += mesg->u.compact.size; } /* end if */ break; default: HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "Invalid layout class"); } /* end switch */ } /* end else */ /* Set return value */ ret_value=mesg; done: if(ret_value==NULL) { if(mesg) H5FL_FREE(H5O_layout_t,mesg); } /* end if */ FUNC_LEAVE_NOAPI(ret_value); }
/*------------------------------------------------------------------------- * Function: H5O_pline_decode * * Purpose: Decodes a filter pipeline message. * * Return: Success: Ptr to the native message. * Failure: NULL * * Programmer: Robb Matzke * Wednesday, April 15, 1998 * *------------------------------------------------------------------------- */ static void * H5O_pline_decode(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, const uint8_t *p) { H5O_pline_t *pline = NULL; /* Pipeline message */ H5Z_filter_info_t *filter; /* Filter to decode */ size_t name_length; /* Length of filter name */ size_t i; /* Local index variable */ void *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* check args */ HDassert(p); /* Allocate space for I/O pipeline message */ if(NULL == (pline = H5FL_CALLOC(H5O_pline_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Version */ pline->version = *p++; if(pline->version < H5O_PLINE_VERSION_1 || pline->version > H5O_PLINE_VERSION_LATEST) HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "bad version number for filter pipeline message") /* Number of filters */ pline->nused = *p++; if(pline->nused > H5Z_MAX_NFILTERS) HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "filter pipeline message has too many filters") /* Reserved */ if(pline->version == H5O_PLINE_VERSION_1) p += 6; /* Allocate array for filters */ pline->nalloc = pline->nused; if(NULL == (pline->filter = (H5Z_filter_info_t *)H5MM_calloc(pline->nalloc * sizeof(pline->filter[0])))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Decode filters */ for(i = 0, filter = &pline->filter[0]; i < pline->nused; i++, filter++) { /* Filter ID */ UINT16DECODE(p, filter->id); /* Length of filter name */ if(pline->version > H5O_PLINE_VERSION_1 && filter->id < H5Z_FILTER_RESERVED) name_length = 0; else { UINT16DECODE(p, name_length); if(pline->version == H5O_PLINE_VERSION_1 && name_length % 8) HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "filter name length is not a multiple of eight") } /* end if */ /* Filter flags */ UINT16DECODE(p, filter->flags); /* Number of filter parameters ("client data elements") */ UINT16DECODE(p, filter->cd_nelmts); /* Filter name, if there is one */ if(name_length) { size_t actual_name_length; /* Actual length of name */ /* Determine actual name length (without padding, but with null terminator) */ actual_name_length = HDstrlen((const char *)p) + 1; HDassert(actual_name_length <= name_length); /* Allocate space for the filter name, or use the internal buffer */ if(actual_name_length > H5Z_COMMON_NAME_LEN) { filter->name = (char *)H5MM_malloc(actual_name_length); if(NULL == filter->name) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for filter name") } /* end if */ else filter->name = filter->_name; HDstrncpy(filter->name, (const char *)p, actual_name_length); p += name_length; } /* end if */
/*------------------------------------------------------------------------- * Function: H5L_extern_traverse * * Purpose: Default traversal function for external links. This can * be overridden using H5Lregister(). * * Given a filename and path packed into the link udata, * attempts to open an object within an external file. * If the H5L_ELINK_PREFIX_NAME property is set in the * link access property list, appends that prefix to the * filename being opened. * * Return: ID of the opened object on success/Negative on failure * * Programmer: James Laird * Monday, July 10, 2006 * Modifications: * Vailin Choi, April 2, 2008 * Add handling to search for the target file * See description in RM: H5Lcreate_external * * Vailin Choi; Sept. 12th, 2008; bug #1247 * Retrieve the file access property list identifer that is set * for link access property via H5Pget_elink_fapl(). * If the return value is H5P_DEFAULT, the parent's file access * property is used to H5F_open() the target file; * Otherwise, the file access property retrieved from H5Pget_elink_fapl() * is used to H5F_open() the target file. * * Vailin Choi; Nov 2010 * Free memory pointed to by tmp_env_prefix for HDF5_EXT_PREFIX case. * *------------------------------------------------------------------------- */ static hid_t H5L_extern_traverse(const char H5_ATTR_UNUSED *link_name, hid_t cur_group, const void *_udata, size_t H5_ATTR_UNUSED udata_size, hid_t lapl_id) { H5P_genplist_t *plist; /* Property list pointer */ char *my_prefix; /* Library's copy of the prefix */ H5G_loc_t root_loc; /* Location of root group in external file */ H5G_loc_t loc; /* Location of object */ H5F_t *ext_file = NULL; /* File struct for external file */ const uint8_t *p = (const uint8_t *)_udata; /* Pointer into external link buffer */ const char *file_name; /* Name of file containing external link's object */ char *full_name = NULL; /* File name with prefix */ const char *obj_name; /* Name external link's object */ size_t fname_len; /* Length of external link file name */ unsigned intent; /* File access permissions */ H5L_elink_cb_t cb_info; /* Callback info struct */ hid_t fapl_id = -1; /* File access property list for external link's file */ hid_t ext_obj = -1; /* ID for external link's object */ char *parent_group_name = NULL;/* Temporary pointer to group name */ char local_group_name[H5L_EXT_TRAVERSE_BUF_SIZE]; /* Local buffer to hold group name */ char *temp_file_name = NULL; /* Temporary pointer to file name */ size_t temp_file_name_len; /* Length of temporary file name */ char *actual_file_name = NULL; /* Parent file's actual name */ H5P_genplist_t *fa_plist; /* File access property list pointer */ H5F_close_degree_t fc_degree = H5F_CLOSE_WEAK; /* File close degree for target file */ hid_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Sanity checks */ HDassert(p); /* Check external link version & flags */ if(((*p >> 4) & 0x0F) > H5L_EXT_VERSION) HGOTO_ERROR(H5E_LINK, H5E_CANTDECODE, FAIL, "bad version number for external link") if((*p & 0x0F) & ~H5L_EXT_FLAGS_ALL) HGOTO_ERROR(H5E_LINK, H5E_CANTDECODE, FAIL, "bad flags for external link") p++; /* Gather some information from the external link's user data */ file_name = (const char *)p; fname_len = HDstrlen(file_name); obj_name = (const char *)p + fname_len + 1; /* Get the plist structure */ if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Get the fapl_id set for lapl_id if any */ if(H5P_get(plist, H5L_ACS_ELINK_FAPL_NAME, &fapl_id) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fapl for links") /* Get the location for the group holding the external link */ if(H5G_loc(cur_group, &loc) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get object location") /* get the access flags set for lapl_id if any */ if(H5P_get(plist, H5L_ACS_ELINK_FLAGS_NAME, &intent) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get elink file access flags") /* get the file access mode flags for the parent file, if they were not set * on lapl_id */ if(intent == H5F_ACC_DEFAULT) intent = H5F_INTENT(loc.oloc->file); if((fapl_id == H5P_DEFAULT) && ((fapl_id = H5F_get_access_plist(loc.oloc->file, FALSE)) < 0)) HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get parent's file access property list") /* Get callback_info */ if(H5P_get(plist, H5L_ACS_ELINK_CB_NAME, &cb_info)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get elink callback info") /* Get file access property list */ if(NULL == (fa_plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS))) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") /* Make callback if it exists */ if(cb_info.func) { const char *parent_file_name; /* Parent file name */ ssize_t group_name_len; /* Length of parent group name */ /* Get parent file name */ parent_file_name = H5F_OPEN_NAME(loc.oloc->file); /* Query length of parent group name */ if((group_name_len = H5G_get_name(&loc, NULL, (size_t) 0, NULL, lapl_id, H5AC_ind_dxpl_id)) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to retrieve length of group name") /* Account for null terminator */ group_name_len++; /* Check if we need to allocate larger buffer */ if((size_t)group_name_len > sizeof(local_group_name)) { if(NULL == (parent_group_name = (char *)H5MM_malloc((size_t)group_name_len))) HGOTO_ERROR(H5E_LINK, H5E_CANTALLOC, FAIL, "can't allocate buffer to hold group name, group_name_len = %Zu", group_name_len) } /* end if */ else parent_group_name = local_group_name; /* Get parent group name */ if(H5G_get_name(&loc, parent_group_name, (size_t) group_name_len, NULL, lapl_id, H5AC_ind_dxpl_id) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "unable to retrieve group name") /* Make callback */ if((cb_info.func)(parent_file_name, parent_group_name, file_name, obj_name, &intent, fapl_id, cb_info.user_data) < 0) HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "traversal operator failed") /* Check access flags */ if((intent & H5F_ACC_TRUNC) || (intent & H5F_ACC_EXCL)) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file open flags") } /* end if */
/*------------------------------------------------------------------------- * Function: H5C_apply_candidate_list * * Purpose: Apply the supplied candidate list. * * We used to do this by simply having each process write * every mpi_size-th entry in the candidate list, starting * at index mpi_rank, and mark all the others clean. * * However, this can cause unnecessary contention in a file * system by increasing the number of processes writing to * adjacent locations in the HDF5 file. * * To attempt to minimize this, we now arange matters such * that each process writes n adjacent entries in the * candidate list, and marks all others clean. We must do * this in such a fashion as to guarantee that each entry * on the candidate list is written by exactly one process, * and marked clean by all others. * * To do this, first construct a table mapping mpi_rank * to the index of the first entry in the candidate list to * be written by the process of that mpi_rank, and then use * the table to control which entries are written and which * are marked as clean as a function of the mpi_rank. * * Note that the table must be identical on all processes, as * all see the same candidate list, mpi_size, and mpi_rank -- * the inputs used to construct the table. * * We construct the table as follows. Let: * * n = num_candidates / mpi_size; * * m = num_candidates % mpi_size; * * Now allocate an array of integers of length mpi_size + 1, * and call this array candidate_assignment_table. * * Conceptually, if the number of candidates is a multiple * of the mpi_size, we simply pass through the candidate list * and assign n entries to each process to flush, with the * index of the first entry to flush in the location in * the candidate_assignment_table indicated by the mpi_rank * of the process. * * In the more common case in which the candidate list isn't * isn't a multiple of the mpi_size, we pretend it is, and * give num_candidates % mpi_size processes one extra entry * each to make things work out. * * Once the table is constructed, we determine the first and * last entry this process is to flush as follows: * * first_entry_to_flush = candidate_assignment_table[mpi_rank] * * last_entry_to_flush = * candidate_assignment_table[mpi_rank + 1] - 1; * * With these values determined, we simply scan through the * candidate list, marking all entries in the range * [first_entry_to_flush, last_entry_to_flush] for flush, * and all others to be cleaned. * * Finally, we scan the LRU from tail to head, flushing * or marking clean the candidate entries as indicated. * If necessary, we scan the pinned list as well. * * Note that this function will fail if any protected or * clean entries appear on the candidate list. * * This function is used in managing sync points, and * shouldn't be used elsewhere. * * Return: Success: SUCCEED * * Failure: FAIL * * Programmer: John Mainzer * 3/17/10 * * Changes: Ported code to detect next entry status changes as the * the result of a flush from the serial code in the scan of * the LRU. Also added code to detect and adapt to the * removal from the cache of the next entry in the scan of * the LRU. * * Note that at present, all of these changes should not * be required as the operations on entries as they are * flushed that can cause these condiditions are not premitted * in the parallel case. However, Quincey indicates that * this may change, and thus has requested the modification. * * Note the assert(FALSE) in the if statement whose body * restarts the scan of the LRU. As the body of the if * statement should be unreachable, it should never be * triggered until the constraints on the parallel case * are relaxed. Please remove the assertion at that time. * * Also added warning on the Pinned Entry List scan, as it * is potentially subject to the same issue. As there is * no cognate of this scan in the serial code, I don't have * a fix to port to it. * * JRM -- 4/10/19 * *------------------------------------------------------------------------- */ herr_t H5C_apply_candidate_list(H5F_t * f, hid_t dxpl_id, H5C_t * cache_ptr, int num_candidates, haddr_t * candidates_list_ptr, int mpi_rank, int mpi_size) { hbool_t restart_scan; hbool_t prev_is_dirty; int i; int m; int n; int first_entry_to_flush; int last_entry_to_flush; int entries_to_clear = 0; int entries_to_flush = 0; int entries_to_flush_or_clear_last = 0; int entries_to_flush_collectively = 0; int entries_cleared = 0; int entries_flushed = 0; int entries_delayed = 0; int entries_flushed_or_cleared_last = 0; int entries_flushed_collectively = 0; int entries_examined = 0; int initial_list_len; int * candidate_assignment_table = NULL; haddr_t addr; H5C_cache_entry_t * clear_ptr = NULL; H5C_cache_entry_t * next_ptr = NULL; H5C_cache_entry_t * entry_ptr = NULL; H5C_cache_entry_t * flush_ptr = NULL; H5C_cache_entry_t * delayed_ptr = NULL; #if H5C_DO_SANITY_CHECKS haddr_t last_addr; #endif /* H5C_DO_SANITY_CHECKS */ #if H5C_APPLY_CANDIDATE_LIST__DEBUG char tbl_buf[1024]; #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) HDassert( cache_ptr != NULL ); HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); HDassert( num_candidates > 0 ); HDassert( num_candidates <= cache_ptr->slist_len ); HDassert( candidates_list_ptr != NULL ); HDassert( 0 <= mpi_rank ); HDassert( mpi_rank < mpi_size ); #if H5C_APPLY_CANDIDATE_LIST__DEBUG HDfprintf(stdout, "%s:%d: setting up candidate assignment table.\n", FUNC, mpi_rank); for ( i = 0; i < 1024; i++ ) tbl_buf[i] = '\0'; sprintf(&(tbl_buf[0]), "candidate list = "); for ( i = 0; i < num_candidates; i++ ) { sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), " 0x%llx", (long long)(*(candidates_list_ptr + i))); } sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), "\n"); HDfprintf(stdout, "%s", tbl_buf); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ n = num_candidates / mpi_size; m = num_candidates % mpi_size; HDassert(n >= 0); if(NULL == (candidate_assignment_table = (int *)H5MM_malloc(sizeof(int) * (size_t)(mpi_size + 1)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for candidate assignment table") candidate_assignment_table[0] = 0; candidate_assignment_table[mpi_size] = num_candidates; if(m == 0) { /* mpi_size is an even divisor of num_candidates */ HDassert(n > 0); for(i = 1; i < mpi_size; i++) candidate_assignment_table[i] = candidate_assignment_table[i - 1] + n; } /* end if */ else { for(i = 1; i <= m; i++) candidate_assignment_table[i] = candidate_assignment_table[i - 1] + n + 1; if(num_candidates < mpi_size) { for(i = m + 1; i < mpi_size; i++) candidate_assignment_table[i] = num_candidates; } /* end if */ else { for(i = m + 1; i < mpi_size; i++) candidate_assignment_table[i] = candidate_assignment_table[i - 1] + n; } /* end else */ } /* end else */ HDassert((candidate_assignment_table[mpi_size - 1] + n) == num_candidates); #if H5C_DO_SANITY_CHECKS /* verify that the candidate assignment table has the expected form */ for ( i = 1; i < mpi_size - 1; i++ ) { int a, b; a = candidate_assignment_table[i] - candidate_assignment_table[i - 1]; b = candidate_assignment_table[i + 1] - candidate_assignment_table[i]; HDassert( n + 1 >= a ); HDassert( a >= b ); HDassert( b >= n ); } #endif /* H5C_DO_SANITY_CHECKS */ first_entry_to_flush = candidate_assignment_table[mpi_rank]; last_entry_to_flush = candidate_assignment_table[mpi_rank + 1] - 1; #if H5C_APPLY_CANDIDATE_LIST__DEBUG for ( i = 0; i < 1024; i++ ) tbl_buf[i] = '\0'; sprintf(&(tbl_buf[0]), "candidate assignment table = "); for(i = 0; i <= mpi_size; i++) sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), " %d", candidate_assignment_table[i]); sprintf(&(tbl_buf[HDstrlen(tbl_buf)]), "\n"); HDfprintf(stdout, "%s", tbl_buf); HDfprintf(stdout, "%s:%d: flush entries [%d, %d].\n", FUNC, mpi_rank, first_entry_to_flush, last_entry_to_flush); HDfprintf(stdout, "%s:%d: marking entries.\n", FUNC, mpi_rank); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ for(i = 0; i < num_candidates; i++) { addr = candidates_list_ptr[i]; HDassert( H5F_addr_defined(addr) ); #if H5C_DO_SANITY_CHECKS if ( i > 0 ) { if ( last_addr == addr ) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Duplicate entry in cleaned list.\n") } else if ( last_addr > addr ) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "candidate list not sorted.\n") } } last_addr = addr; #endif /* H5C_DO_SANITY_CHECKS */ H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL) if(entry_ptr == NULL) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Listed candidate entry not in cache?!?!?.") } else if(!entry_ptr->is_dirty) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Listed entry not dirty?!?!?.") } else if ( entry_ptr->is_protected ) { /* For now at least, we can't deal with protected entries. * If we encounter one, scream and die. If it becomes an * issue, we should be able to work around this. */ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Listed entry is protected?!?!?.") } else { /* determine whether the entry is to be cleared or flushed, * and mark it accordingly. We will scan the protected and * pinned list shortly, and clear or flush according to these * markings. */ if((i >= first_entry_to_flush) && (i <= last_entry_to_flush)) { entries_to_flush++; entry_ptr->flush_immediately = TRUE; } /* end if */ else { entries_to_clear++; entry_ptr->clear_on_unprotect = TRUE; } /* end else */ } /* end else */ } /* end for */ #if H5C_APPLY_CANDIDATE_LIST__DEBUG HDfprintf(stdout, "%s:%d: num candidates/to clear/to flush = %d/%d/%d.\n", FUNC, mpi_rank, (int)num_candidates, (int)entries_to_clear, (int)entries_to_flush); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ /* We have now marked all the entries on the candidate list for * either flush or clear -- now scan the LRU and the pinned list * for these entries and do the deed. * * Note that we are doing things in this round about manner so as * to preserve the order of the LRU list to the best of our ability. * If we don't do this, my experiments indicate that we will have a * noticably poorer hit ratio as a result. */ #if H5C_APPLY_CANDIDATE_LIST__DEBUG HDfprintf(stdout, "%s:%d: scanning LRU list. len = %d.\n", FUNC, mpi_rank, (int)(cache_ptr->LRU_list_len)); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ /* ===================================================================== * * Now scan the LRU and PEL lists, flushing or clearing entries as * needed. * * The flush_me_last and flush_me_collectively flags may dictate how or * when some entries can be flushed, and should be addressed here. * However, in their initial implementation, these flags only apply to the * superblock, so there's only a relatively small change to this function * to account for this one case where they come into play. If these flags * are ever expanded upon, this function and the following flushing steps * should be reworked to account for additional cases. * ===================================================================== */ HDassert(entries_to_flush >= 0); restart_scan = FALSE; entries_examined = 0; initial_list_len = cache_ptr->LRU_list_len; entry_ptr = cache_ptr->LRU_tail_ptr; /* Examine each entry in the LRU list */ while ( ( entry_ptr != NULL ) && ( entries_examined <= (entries_to_flush + 1) * initial_list_len ) && ( (entries_cleared + entries_flushed) < num_candidates ) ) { if ( entry_ptr->prev != NULL ) prev_is_dirty = entry_ptr->prev->is_dirty; /* If this process needs to clear this entry. */ if(entry_ptr->clear_on_unprotect) { HDassert(entry_ptr->is_dirty); next_ptr = entry_ptr->next; entry_ptr->clear_on_unprotect = FALSE; clear_ptr = entry_ptr; entry_ptr = entry_ptr->prev; entries_cleared++; #if ( H5C_APPLY_CANDIDATE_LIST__DEBUG > 1 ) HDfprintf(stdout, "%s:%d: clearing 0x%llx.\n", FUNC, mpi_rank, (long long)clear_ptr->addr); #endif /* H5C_APPLY_CANDIDATE_LIST__DEBUG */ /* No need to check for the next entry in the scan being * removed from the cache, as this call to H5C__flush_single_entry() * will not call either the pre_serialize or serialize callbacks. */ if(H5C__flush_single_entry(f, dxpl_id, clear_ptr, H5C__FLUSH_CLEAR_ONLY_FLAG | H5C__DEL_FROM_SLIST_ON_DESTROY_FLAG, NULL) < 0) HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't clear entry.") } /* end if */ /* Else, if this process needs to flush this entry. */ else if (entry_ptr->flush_immediately) {
/*-------------------------------------------------------------------------- NAME H5R__create PURPOSE Creates a particular kind of reference for the user USAGE herr_t H5R__create(ref, loc, name, ref_type, space) void *ref; OUT: Reference created H5G_loc_t *loc; IN: File location used to locate object pointed to const char *name; IN: Name of object at location LOC_ID of object pointed to H5R_type_t ref_type; IN: Type of reference to create H5S_t *space; IN: Dataspace ID with selection, used for Dataset Region references. RETURNS Non-negative on success/Negative on failure DESCRIPTION Creates a particular type of reference specified with REF_TYPE, in the space pointed to by REF. The LOC_ID and NAME are used to locate the object pointed to and the SPACE_ID is used to choose the region pointed to (for Dataset Region references). GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ herr_t H5R__create(void *_ref, H5G_loc_t *loc, const char *name, H5R_type_t ref_type, H5S_t *space) { H5G_loc_t obj_loc; /* Group hier. location of object */ H5G_name_t path; /* Object group hier. path */ H5O_loc_t oloc; /* Object object location */ hbool_t obj_found = FALSE; /* Object location found */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE_VOL HDassert(_ref); HDassert(loc); HDassert(name); HDassert(ref_type > H5R_BADTYPE && ref_type < H5R_MAXTYPE); /* Set up object location to fill in */ obj_loc.oloc = &oloc; obj_loc.path = &path; H5G_loc_reset(&obj_loc); /* Find the object */ if(H5G_loc_find(loc, name, &obj_loc) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_NOTFOUND, FAIL, "object not found") obj_found = TRUE; switch (ref_type) { case H5R_OBJECT: { hobj_ref_t *ref = (hobj_ref_t *)_ref; /* Get pointer to correct type of reference struct */ *ref = obj_loc.oloc->addr; break; } case H5R_DATASET_REGION: { H5HG_t hobjid; /* Heap object ID */ hdset_reg_ref_t *ref = (hdset_reg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ hssize_t buf_size; /* Size of buffer needed to serialize selection */ uint8_t *p; /* Pointer to OID to store */ uint8_t *buf; /* Buffer to store serialized selection in */ unsigned heapid_found; /* Flag for non-zero heap ID found */ unsigned u; /* local index */ /* Set up information for dataset region */ /* Return any previous heap block to the free list if we are * garbage collecting */ if (H5F_GC_REF(loc->oloc->file)) { /* Check for an existing heap ID in the reference */ for (u = 0, heapid_found = 0, p = (uint8_t *)ref; u < H5R_DSET_REG_REF_BUF_SIZE; u++) if (p[u] != 0) { heapid_found = 1; break; } if (heapid_found != 0) { /* Return heap block to free list */ } } /* Zero the heap ID out, may leak heap space if user is re-using * reference and doesn't have garbage collection turned on */ HDmemset(ref, 0, H5R_DSET_REG_REF_BUF_SIZE); /* Get the amount of space required to serialize the selection */ if ((buf_size = H5S_SELECT_SERIAL_SIZE(space, loc->oloc->file)) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "Invalid amount of space for serializing selection") /* Increase buffer size to allow for the dataset OID */ buf_size += (hssize_t)sizeof(haddr_t); /* Allocate the space to store the serialized information */ H5_CHECK_OVERFLOW(buf_size, hssize_t, size_t); if (NULL == (buf = (uint8_t *)H5MM_malloc((size_t)buf_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Serialize information for dataset OID into heap buffer */ p = (uint8_t *)buf; H5F_addr_encode(loc->oloc->file, &p, obj_loc.oloc->addr); /* Serialize the selection into heap buffer */ if (H5S_SELECT_SERIALIZE(space, &p, loc->oloc->file) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Unable to serialize selection") /* Save the serialized buffer for later */ H5_CHECK_OVERFLOW(buf_size, hssize_t, size_t); if(H5HG_insert(loc->oloc->file, (size_t)buf_size, buf, &hobjid) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_WRITEERROR, FAIL, "Unable to serialize selection") /* Serialize the heap ID and index for storage in the file */ p = (uint8_t *)ref; H5F_addr_encode(loc->oloc->file, &p, hobjid.addr); UINT32ENCODE(p, hobjid.idx); /* Free the buffer we serialized data in */ H5MM_xfree(buf); break; } /* end case H5R_DATASET_REGION */ case H5R_BADTYPE: case H5R_MAXTYPE: default: HDassert("unknown reference type" && 0); HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)") } /* end switch */ done: if (obj_found) H5G_loc_free(&obj_loc); FUNC_LEAVE_NOAPI_VOL(ret_value) } /* end H5R__create() */