/*------------------------------------------------------------------------- * Function: H5O_layout_encode * * Purpose: Encodes a message. * * Return: Non-negative on success/Negative on failure * * 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 herr_t H5O_layout_encode(H5F_t *f, uint8_t *p, const void *_mesg) { const H5O_layout_t *mesg = (const H5O_layout_t *) _mesg; unsigned u; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_layout_encode); /* check args */ assert(f); assert(mesg); assert(mesg->version>0); assert(p); /* Version */ *p++ = mesg->version; /* Check for which information to write */ if(mesg->version<3) { /* number of dimensions */ if(mesg->type!=H5D_CHUNKED) { assert(mesg->unused.ndims > 0 && mesg->unused.ndims <= H5O_LAYOUT_NDIMS); *p++ = mesg->unused.ndims; } /* end if */ else { assert(mesg->u.chunk.ndims > 0 && mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS); *p++ = mesg->u.chunk.ndims; } /* end else */ /* layout class */ *p++ = mesg->type; /* reserved bytes should be zero */ for (u=0; u<5; u++) *p++ = 0; /* data or B-tree address */ if(mesg->type==H5D_CONTIGUOUS) H5F_addr_encode(f, &p, mesg->u.contig.addr); else if(mesg->type==H5D_CHUNKED) H5F_addr_encode(f, &p, mesg->u.chunk.addr); /* Dimension sizes */ if(mesg->type!=H5D_CHUNKED) for (u = 0; u < mesg->unused.ndims; u++) UINT32ENCODE(p, mesg->unused.dim[u]) else for (u = 0; u < mesg->u.chunk.ndims; u++) UINT32ENCODE(p, mesg->u.chunk.dim[u]); if(mesg->type==H5D_COMPACT) { UINT32ENCODE(p, mesg->u.compact.size); if(mesg->u.compact.size>0 && mesg->u.compact.buf) { HDmemcpy(p, mesg->u.compact.buf, mesg->u.compact.size); p += mesg->u.compact.size; } } } /* end if */ else {
/*-------------------------------------------------------------------------- NAME H5S_none_serialize PURPOSE Serialize the current selection into a user-provided buffer. USAGE herr_t H5S_none_serialize(space, buf) H5S_t *space; IN: Dataspace pointer of selection to serialize uint8 *buf; OUT: Buffer to put serialized selection into RETURNS Non-negative on success/Negative on failure DESCRIPTION Serializes the current element selection into a buffer. (Primarily for storing on disk). GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ static herr_t H5S_none_serialize (const H5S_t *space, uint8_t *buf) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_serialize); assert(space); /* Store the preamble information */ UINT32ENCODE(buf, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */ UINT32ENCODE(buf, (uint32_t)1); /* Store the version number */ UINT32ENCODE(buf, (uint32_t)0); /* Store the un-used padding */ UINT32ENCODE(buf, (uint32_t)0); /* Store the additional information length */ FUNC_LEAVE_NOAPI(SUCCEED); } /* H5S_none_serialize() */
/*------------------------------------------------------------------------- * Function: H5O_mtime_new_encode * * Purpose: Encodes a new modification time message. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Jan 3 2002 * *------------------------------------------------------------------------- */ static herr_t H5O_mtime_new_encode(H5F_t UNUSED *f, hbool_t UNUSED disable_shared, uint8_t *p, const void *_mesg) { const time_t *mesg = (const time_t *) _mesg; FUNC_ENTER_NOAPI_NOINIT_NOERR /* check args */ assert(f); assert(p); assert(mesg); /* Version */ *p++ = H5O_MTIME_VERSION; /* Reserved bytes */ *p++ = 0; *p++ = 0; *p++ = 0; /* Encode time */ UINT32ENCODE(p, *mesg); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_mtime_new_encode() */
/**************************************************************** ** ** test_metadata(): Main meta-data encode/decode testing routine. ** ****************************************************************/ void test_metadata(void) { int16_t ei16 = TEST_INT16_VALUE; /* variables to hold the values to encode */ uint16_t eu16 = TEST_UINT16_VALUE; int32_t ei32 = TEST_INT32_VALUE; uint32_t eu32 = TEST_UINT32_VALUE; int16_t di16; /* variables to hold the decoded values */ uint16_t du16; int32_t di32; uint32_t du32; uint8_t *p; /* pointer into the buffer being en/de-coded */ /* Output message about test being performed */ MESSAGE(5, ("Testing Metadata Encoding/decoding\n")); /* Start by encoding the values above */ p = encode_buffer; INT16ENCODE(p, ei16); /* Encode the int16 value */ UINT16ENCODE(p, eu16); /* Encode the uint16 value */ INT32ENCODE(p, ei32); /* Encode the int32 value */ UINT32ENCODE(p, eu32); /* Encode the uint32 value */ /* Check if we got what we asked for */ if (HDmemcmp(encode_buffer, compar_buffer, sizeof(compar_buffer)) != 0) { unsigned u; /* local counting variable */ for (u = 0; u < sizeof(compar_buffer); u++) { if (compar_buffer[u] != encode_buffer[u]) TestErrPrintf("Error encoding meta-data at offset %u, wanted: %u, got: %u\n", (unsigned) u, (unsigned) compar_buffer[u], (unsigned) encode_buffer[u]); } /* end for */ } /* end if */ /* Test decoding macros */ p = encode_buffer; INT16DECODE(p, di16); /* Decode the int16 value */ UINT16DECODE(p, du16); /* Decode the uint16 value */ INT32DECODE(p, di32); /* Decode the int32 value */ UINT32DECODE(p, du32); /* Decode the uint32 value */ /* Check the values decoded */ if (di16 != TEST_INT16_VALUE) TestErrPrintf("Error decoding int16 meta-data wanted: %d, got: %d " "at %s:%d\n", (int) TEST_INT16_VALUE, (int) di16, __FILE__, __LINE__); if (du16 != TEST_UINT16_VALUE) TestErrPrintf("Error decoding uint16 meta-data wanted: %u, got: %u " "at %s:%d\n", (unsigned) TEST_UINT16_VALUE, (unsigned) du16, __FILE__, __LINE__); if (di32 != TEST_INT32_VALUE) TestErrPrintf("Error decoding int32 meta-data wanted: %ld, got: %ld " "at %s:%d\n", (long) TEST_INT32_VALUE, (long) di32, __FILE__, __LINE__); if (du32 != TEST_UINT32_VALUE) TestErrPrintf("Error decoding uint32 meta-data wanted: %lu, got: %lu " "at %s:%d\n", (unsigned long) TEST_UINT32_VALUE, (unsigned long) du32, __FILE__, __LINE__); } /* test_metadata() */
/*------------------------------------------------------------------------- * Function: H5O_bogus_encode * * Purpose: Encodes a "bogus" message. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Jan 21 2003 * *------------------------------------------------------------------------- */ static herr_t H5O_bogus_encode(H5F_t UNUSED *f, hbool_t UNUSED disable_shared, uint8_t *p, const void UNUSED *mesg) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_bogus_encode) /* check args */ HDassert(f); HDassert(p); HDassert(mesg); /* encode */ UINT32ENCODE(p, H5O_BOGUS_VALUE); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_bogus_encode() */
/*------------------------------------------------------------------------- * Function: H5O_fill_encode * * Purpose: Encode a fill value message. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Thursday, October 1, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5O_fill_encode(H5F_t UNUSED *f, uint8_t *p, const void *_mesg) { const H5O_fill_t *mesg = (const H5O_fill_t *)_mesg; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_fill_encode); assert(f); assert(p); assert(mesg && NULL==mesg->type); UINT32ENCODE(p, mesg->size); if(mesg->buf) HDmemcpy(p, mesg->buf, mesg->size); FUNC_LEAVE_NOAPI(SUCCEED); }
/*------------------------------------------------------------------------- * Function: H5O_refcount_encode * * Purpose: Encodes a message. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Mar 10 2007 * *------------------------------------------------------------------------- */ static herr_t H5O_refcount_encode(H5F_t H5_ATTR_UNUSED *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p, const void *_mesg) { const H5O_refcount_t *refcount = (const H5O_refcount_t *)_mesg; FUNC_ENTER_NOAPI_NOINIT_NOERR /* check args */ HDassert(f); HDassert(p); HDassert(refcount); /* Message version */ *p++ = H5O_REFCOUNT_VERSION; /* Object's ref. count */ UINT32ENCODE(p, *refcount); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_refcount_encode() */
/*------------------------------------------------------------------------- * Function: H5O_layout_encode * * Purpose: Encodes a message. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Wednesday, October 8, 1997 * * Note: * Quincey Koziol, 2004-5-21 * We write out version 3 messages by default now. * * 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. * * Quincey Koziol, 2004-5-21 * Added version number 3 case to straighten out problems with contiguous * layout's sizes (was encoding them as 4-byte values when they were * really n-byte values (where n usually is 8)) and additionally clean up * the information written out. * *------------------------------------------------------------------------- */ static herr_t H5O_layout_encode(H5F_t *f, hbool_t UNUSED disable_shared, uint8_t *p, const void *_mesg) { const H5O_layout_t *mesg = (const H5O_layout_t *) _mesg; unsigned u; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_layout_encode) /* check args */ HDassert(f); HDassert(mesg); HDassert(p); /* Message version */ *p++ = (uint8_t)H5O_LAYOUT_VERSION_3; /* Layout class */ *p++ = mesg->type; /* Write out layout class specific information */ switch(mesg->type) { case H5D_COMPACT: /* Size of raw data */ UINT16ENCODE(p, mesg->storage.u.compact.size); /* Raw data */ if(mesg->storage.u.compact.size > 0) { if(mesg->storage.u.compact.buf) HDmemcpy(p, mesg->storage.u.compact.buf, mesg->storage.u.compact.size); else HDmemset(p, 0, mesg->storage.u.compact.size); p += mesg->storage.u.compact.size; } /* end if */ break; case H5D_CONTIGUOUS: H5F_addr_encode(f, &p, mesg->storage.u.contig.addr); H5F_ENCODE_LENGTH(f, p, mesg->storage.u.contig.size); break; case H5D_CHUNKED: /* Number of dimensions */ HDassert(mesg->u.chunk.ndims > 0 && mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS); *p++ = (uint8_t)mesg->u.chunk.ndims; /* B-tree address */ H5F_addr_encode(f, &p, mesg->storage.u.chunk.idx_addr); /* Dimension sizes */ for(u = 0; u < mesg->u.chunk.ndims; u++) UINT32ENCODE(p, mesg->u.chunk.dim[u]); break; default: HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "Invalid layout class") } /* end switch */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_layout_encode() */
/*-------------------------------------------------------------------------- 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() */
/*------------------------------------------------------------------------- * Function: H5B2_cache_hdr_flush * * Purpose: Flushes a dirty B-tree header to disk. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Feb 1 2005 * Changes: JRM -- 8/21/06 * Added the flags_ptr parameter. This parameter exists to * allow the flush routine to report to the cache if the * entry is resized or renamed as a result of the flush. * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry. * *------------------------------------------------------------------------- */ static herr_t H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_t *bt2, unsigned UNUSED * flags_ptr) { H5WB_t *wb = NULL; /* Wrapped buffer for header data */ uint8_t hdr_buf[H5B2_HDR_BUF_SIZE]; /* Buffer for header */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5B2_cache_hdr_flush, FAIL) /* check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); HDassert(bt2); if (bt2->cache_info.is_dirty) { H5B2_shared_t *shared; /* Shared B-tree information */ uint8_t *hdr; /* Pointer to header buffer */ uint8_t *p; /* Pointer into raw data buffer */ size_t size; /* Header size on disk */ uint32_t metadata_chksum; /* Computed metadata checksum value */ /* Get the pointer to the shared B-tree info */ shared = (H5B2_shared_t *)H5RC_GET_OBJ(bt2->shared); HDassert(shared); /* Wrap the local buffer for serialized header info */ if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf)))) HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't wrap buffer") /* Compute the size of the serialized B-tree header on disk */ size = H5B2_HEADER_SIZE(f); /* Get a pointer to a buffer that's large enough for header */ if(NULL == (hdr = (uint8_t *)H5WB_actual(wb, size))) HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, FAIL, "can't get actual buffer") /* Get temporary pointer to serialized header */ p = hdr; /* Magic number */ HDmemcpy(p, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC); p += H5_SIZEOF_MAGIC; /* Version # */ *p++ = H5B2_HDR_VERSION; /* B-tree type */ *p++ = shared->type->id; /* Node size (in bytes) */ UINT32ENCODE(p, shared->node_size); /* Raw key size (in bytes) */ UINT16ENCODE(p, shared->rrec_size); /* Depth of tree */ UINT16ENCODE(p, shared->depth); /* Split & merge %s */ H5_CHECK_OVERFLOW(shared->split_percent, /* From: */ unsigned, /* To: */ uint8_t); *p++ = (uint8_t)shared->split_percent; H5_CHECK_OVERFLOW(shared->merge_percent, /* From: */ unsigned, /* To: */ uint8_t); *p++ = (uint8_t)shared->merge_percent; /* Root node pointer */ H5F_addr_encode(f, &p, bt2->root.addr); UINT16ENCODE(p, bt2->root.node_nrec); H5F_ENCODE_LENGTH(f, p, bt2->root.all_nrec); /* Compute metadata checksum */ metadata_chksum = H5_checksum_metadata(hdr, (size - H5B2_SIZEOF_CHKSUM), 0); /* Metadata checksum */ UINT32ENCODE(p, metadata_chksum); /* Write the B-tree header. */ HDassert((size_t)(p - hdr) == size); if(H5F_block_write(f, H5FD_MEM_BTREE, addr, size, dxpl_id, hdr) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree header to disk") bt2->cache_info.is_dirty = FALSE; } /* end if */