/*------------------------------------------------------------------------- * Function: H5SM__bt2_crt_context * * Purpose: Create client callback context * * Return: Success: non-NULL * Failure: NULL * * Programmer: Quincey Koziol * Thursday, November 26, 2009 * *------------------------------------------------------------------------- */ static void * H5SM__bt2_crt_context(void *_f) { H5F_t *f = (H5F_t *)_f; /* User data for building callback context */ H5SM_bt2_ctx_t *ctx; /* Callback context structure */ void *ret_value = NULL; /* Return value */ FUNC_ENTER_STATIC /* Sanity check */ HDassert(f); /* Allocate callback context */ if(NULL == (ctx = H5FL_MALLOC(H5SM_bt2_ctx_t))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate callback context") /* Determine the size of addresses & lengths in the file */ ctx->sizeof_addr = H5F_SIZEOF_ADDR(f); /* Set return value */ ret_value = ctx; done: FUNC_LEAVE_NOAPI(ret_value) } /* H5SM__bt2_crt_context() */
/*------------------------------------------------------------------------- * Function: H5O_ainfo_size * * Purpose: Returns the size of the raw message in bytes not counting * the message type or size fields, but only the data fields. * This function doesn't take into account alignment. * * Return: Success: Message data size in bytes without alignment. * Failure: zero * * Programmer: Quincey Koziol * [email protected] * Mar 6 2007 * *------------------------------------------------------------------------- */ static size_t H5O_ainfo_size(const H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, const void *_mesg) { const H5O_ainfo_t *ainfo = (const H5O_ainfo_t *)_mesg; size_t ret_value = 0; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Set return value */ ret_value = (size_t)(1 /* Version */ + 1 /* Index flags */ + (ainfo->track_corder ? 2 : 0) /* Curr. max. creation order value */ + H5F_SIZEOF_ADDR(f) /* Address of fractal heap to store "dense" attributes */ + H5F_SIZEOF_ADDR(f) /* Address of v2 B-tree for indexing names of attributes */ + (ainfo->index_corder ? H5F_SIZEOF_ADDR(f) : 0)); /* Address of v2 B-tree for indexing creation order values of attributes */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_ainfo_size() */
/*------------------------------------------------------------------------- * Function: H5O_shmesg_size * * Purpose: Returns the size of the raw message in bytes not counting the * message type or size fields, but only the data fields. * * Return: Success: Message data size in bytes w/o alignment. * Failure: 0 * * Programmer: James Laird * Jan 29, 2007 * *------------------------------------------------------------------------- */ static size_t H5O_shmesg_size(const H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, const void H5_ATTR_UNUSED *_mesg) { size_t ret_value; FUNC_ENTER_NOAPI_NOINIT_NOERR /* Sanity check */ HDassert(f); ret_value = (size_t)(1 + /* Version number */ H5F_SIZEOF_ADDR(f) + /* Table address */ 1); /* Number of indexes */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_shmesg_size() */
/*------------------------------------------------------------------------- * Function: H5MF_alloc_overflow * * Purpose: Checks if an allocation of file space would cause an overflow. * F is the file whose space is being allocated, SIZE is the amount * of space needed. * * Return: 0 if no overflow would result * 1 if overflow would result (the allocation should not be allowed) * * Programmer: James Laird * Nat Furrer * Tuesday, June 1, 2004 * * Modifications: *------------------------------------------------------------------------- */ hbool_t H5MF_alloc_overflow(H5F_t *f, hsize_t size) { hsize_t space_needed; /* Accumulator variable */ size_t c; /* Local index variable */ hbool_t ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOFUNC(H5MF_alloc_overflow) /* Start with the current end of the file's address. */ space_needed = (hsize_t)H5F_get_eoa(f); HDassert(H5F_addr_defined(space_needed)); /* Subtract the file's base address to get the actual amount of * space being used: * (end of allocated space - beginning of allocated space) */ HDassert(H5F_BASE_ADDR(f) < space_needed); space_needed -= (hsize_t)H5F_BASE_ADDR(f); /* Add the amount of space requested for this allocation */ space_needed += size; /* Also add space that is "reserved" for data to be flushed * to disk (e.g., for object headers and the heap). * This is the total amount of file space that will be * allocated. */ space_needed += f->shared->lf->reserved_alloc; /* Ensure that this final number is less than the file's * address space. We do this by shifting in multiples * of 16 bits because some systems will do nothing if * we shift by the size of a long long (64 bits) all at * once (<cough> Linux <cough>). Thus, we break one shift * into several smaller shifts. */ for(c=0; c < H5F_SIZEOF_ADDR(f); c += 2) space_needed = space_needed >> 16; if(space_needed != 0) ret_value=TRUE; else ret_value=FALSE; FUNC_LEAVE_NOAPI(ret_value) }
/*------------------------------------------------------------------------- * Function: H5O_efl_size * * Purpose: Returns the size of the raw message in bytes not counting the * message type or size fields, but only the data fields. This * function doesn't take into account message alignment. This * function doesn't count unused slots. * * Return: Success: Message data size in bytes. * * Failure: 0 * * Programmer: Robb Matzke * Tuesday, November 25, 1997 * *------------------------------------------------------------------------- */ static size_t H5O_efl_size(const H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, const void *_mesg) { const H5O_efl_t *mesg = (const H5O_efl_t *) _mesg; size_t ret_value = 0; FUNC_ENTER_NOAPI_NOINIT_NOERR /* check args */ HDassert(f); HDassert(mesg); ret_value = (size_t)H5F_SIZEOF_ADDR(f) + /*heap address */ 2 + /*slots allocated*/ 2 + /*num slots used*/ 4 + /*reserved */ mesg->nused * ((size_t)H5F_SIZEOF_SIZE(f) + /*name offset */ (size_t)H5F_SIZEOF_SIZE(f) + /*file offset */ (size_t)H5F_SIZEOF_SIZE(f)); /*file size */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_efl_size() */
/*------------------------------------------------------------------------- * Function: H5SM_bt2_crt_dbg_context * * Purpose: Create context for debugging callback * * Return: Success: non-NULL * Failure: NULL * * Programmer: Quincey Koziol * Tuesday, December 1, 2009 * *------------------------------------------------------------------------- */ static void * H5SM_bt2_crt_dbg_context(H5F_t *f, hid_t H5_ATTR_UNUSED dxpl_id, haddr_t H5_ATTR_UNUSED addr) { H5SM_bt2_ctx_t *ctx; /* Callback context structure */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Sanity check */ HDassert(f); /* Allocate callback context */ if(NULL == (ctx = H5FL_MALLOC(H5SM_bt2_ctx_t))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate callback context") /* Determine the size of addresses & lengths in the file */ ctx->sizeof_addr = H5F_SIZEOF_ADDR(f); /* Set return value */ ret_value = ctx; done: FUNC_LEAVE_NOAPI(ret_value) } /* H5SM_bt2_crt_dbg_context() */
/*------------------------------------------------------------------------- * Function: H5D__layout_meta_size * * Purpose: Returns the size of the raw message in bytes except raw data * part for compact dataset. This function doesn't take into * account message alignment. * * Return: Success: Message data size in bytes * Failure: 0 * * Programmer: Raymond Lu * August 14, 2002 * *------------------------------------------------------------------------- */ size_t H5D__layout_meta_size(const H5F_t *f, const H5O_layout_t *layout, hbool_t include_compact_data) { size_t ret_value = 0; /* Return value */ FUNC_ENTER_PACKAGE /* check args */ HDassert(f); HDassert(layout); ret_value = 1 + /* Version number */ 1; /* layout class type */ switch(layout->type) { case H5D_COMPACT: /* This information only present in older versions of message */ /* Size of raw data */ ret_value += 2; if(include_compact_data) ret_value += layout->storage.u.compact.size; /* data for compact dataset */ break; case H5D_CONTIGUOUS: /* This information only present in older versions of message */ ret_value += H5F_SIZEOF_ADDR(f); /* Address of data */ ret_value += H5F_SIZEOF_SIZE(f); /* Length of data */ break; case H5D_CHUNKED: if(layout->version < H5O_LAYOUT_VERSION_4) { /* Number of dimensions (1 byte) */ HDassert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS); ret_value++; /* B-tree address */ ret_value += H5F_SIZEOF_ADDR(f); /* Address of data */ /* Dimension sizes */ ret_value += layout->u.chunk.ndims * 4; } /* end if */ else { /* Chunked layout feature flags */ ret_value++; /* Number of dimensions (1 byte) */ HDassert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS); ret_value++; /* Encoded # of bytes for each chunk dimension */ HDassert(layout->u.chunk.enc_bytes_per_dim > 0 && layout->u.chunk.enc_bytes_per_dim <= 8); ret_value++; /* Dimension sizes */ ret_value += layout->u.chunk.ndims * layout->u.chunk.enc_bytes_per_dim; /* Type of chunk index */ ret_value++; switch(layout->u.chunk.idx_type) { case H5D_CHUNK_IDX_BTREE: HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, 0, "v1 B-tree index type found for layout message >v3") case H5D_CHUNK_IDX_NONE: /* nothing */ break; case H5D_CHUNK_IDX_SINGLE: /* Possible filter information */ if(layout->u.chunk.flags & H5O_LAYOUT_CHUNK_SINGLE_INDEX_WITH_FILTER) { ret_value += H5F_SIZEOF_SIZE(f); /* Size of chunk (in file) */ ret_value += 4; /* Filter mask for chunk */ } /* end if */ break; case H5D_CHUNK_IDX_FARRAY: /* Fixed array creation parameters */ ret_value += H5D_FARRAY_CREATE_PARAM_SIZE; break; case H5D_CHUNK_IDX_EARRAY: /* Extensible array creation parameters */ ret_value += H5D_EARRAY_CREATE_PARAM_SIZE; break; case H5D_CHUNK_IDX_BT2: /* v2 B-tree creation parameters */ ret_value += H5D_BT2_CREATE_PARAM_SIZE; break; case H5D_CHUNK_IDX_NTYPES: default: HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, 0, "Invalid chunk index type") } /* end switch */ /* Chunk index address */ ret_value += H5F_SIZEOF_ADDR(f); } /* end else */ break; case H5D_VIRTUAL: ret_value += H5F_SIZEOF_ADDR(f); /* Address of global heap */ ret_value += 4; /* Global heap index */ break; case H5D_LAYOUT_ERROR: case H5D_NLAYOUTS: default: HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, 0, "Invalid layout class") } /* end switch */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__layout_meta_size() */
/*------------------------------------------------------------------------- * Function: H5HL_create * * Purpose: Creates a new heap data structure on disk and caches it * in memory. SIZE_HINT is a hint for the initial size of the * data area of the heap. If size hint is invalid then a * reasonable (but probably not optimal) size will be chosen. * If the heap ever has to grow, then REALLOC_HINT is the * minimum amount by which the heap will grow. * * Return: Success: Non-negative. The file address of new heap is * returned through the ADDR argument. * * Failure: Negative * * Programmer: Robb Matzke * [email protected] * Jul 16 1997 * *------------------------------------------------------------------------- */ herr_t H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/) { H5HL_t *heap = NULL; /* Heap created */ H5HL_prfx_t *prfx = NULL; /* Heap prefix */ hsize_t total_size; /* Total heap size on disk */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* check arguments */ HDassert(f); HDassert(addr_p); /* Adjust size hint as necessary */ if(size_hint && size_hint < H5HL_SIZEOF_FREE(f)) size_hint = H5HL_SIZEOF_FREE(f); size_hint = H5HL_ALIGN(size_hint); /* Allocate new heap structure */ if(NULL == (heap = H5HL_new(H5F_SIZEOF_SIZE(f), H5F_SIZEOF_ADDR(f), H5HL_SIZEOF_HDR(f)))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate new heap struct") /* Allocate file space */ total_size = heap->prfx_size + size_hint; if(HADDR_UNDEF == (heap->prfx_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate file memory") /* Initialize info */ heap->single_cache_obj = TRUE; heap->dblk_addr = heap->prfx_addr + (hsize_t)heap->prfx_size; heap->dblk_size = size_hint; if(size_hint) if(NULL == (heap->dblk_image = H5FL_BLK_CALLOC(lheap_chunk, size_hint))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") /* free list */ if(size_hint) { if(NULL == (heap->freelist = H5FL_MALLOC(H5HL_free_t))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") heap->freelist->offset = 0; heap->freelist->size = size_hint; heap->freelist->prev = heap->freelist->next = NULL; heap->free_block = 0; } /* end if */ else { heap->freelist = NULL; heap->free_block = H5HL_FREE_NULL; } /* end else */ /* Allocate the heap prefix */ if(NULL == (prfx = H5HL_prfx_new(heap))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") /* Add to cache */ if(H5AC_insert_entry(f, dxpl_id, H5AC_LHEAP_PRFX, heap->prfx_addr, prfx, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache local heap prefix") /* Set address to return */ *addr_p = heap->prfx_addr; done: if(ret_value < 0) { if(prfx) { if(H5HL_prfx_dest(prfx) < 0) HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap prefix") } /* end if */ else { if(heap) { if(H5F_addr_defined(heap->prfx_addr)) if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->prfx_addr, total_size) < 0) HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't release heap data?") if(H5HL_dest(heap) < 0) HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap") } /* end if */ } /* end else */ } /* end if */
/*------------------------------------------------------------------------- * Function: H5O_load * * Purpose: Loads an object header from disk. * * Return: Success: Pointer to the new object header. * * Failure: NULL * * Programmer: Robb Matzke * [email protected] * Aug 5 1997 * *------------------------------------------------------------------------- */ static H5O_t * H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, void UNUSED * _udata2) { H5O_t *oh = NULL; /* Object header read in */ uint8_t read_buf[H5O_SPEC_READ_SIZE]; /* Buffer for speculative read */ const uint8_t *p; /* Pointer into buffer to decode */ size_t spec_read_size; /* Size of buffer to speculatively read in */ size_t prefix_size; /* Size of object header prefix */ unsigned nmesgs; /* Total # of messages in this object header */ unsigned curmesg = 0; /* Current message being decoded in object header */ unsigned merged_null_msgs = 0; /* Number of null messages merged together */ haddr_t chunk_addr; /* Address of first chunk */ size_t chunk_size; /* Size of first chunk */ haddr_t eoa; /* Relative end of file address */ H5O_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5O_load, NULL) /* check args */ HDassert(f); HDassert(H5F_addr_defined(addr)); HDassert(!_udata1); HDassert(!_udata2); /* Make certain we don't speculatively read off the end of the file */ if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_OHDR))) HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine file size") /* Compute the size of the speculative object header buffer */ H5_ASSIGN_OVERFLOW(spec_read_size, MIN(eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t); /* Attempt to speculatively read both object header prefix and first chunk */ if(H5F_block_read(f, H5FD_MEM_OHDR, addr, spec_read_size, dxpl_id, read_buf) < 0) HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header") p = read_buf; /* allocate ohdr and init chunk list */ if(NULL == (oh = H5FL_CALLOC(H5O_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* File-specific, non-stored information */ oh->sizeof_size = H5F_SIZEOF_SIZE(f); oh->sizeof_addr = H5F_SIZEOF_ADDR(f); /* Check for magic number */ /* (indicates version 2 or later) */ if(!HDmemcmp(p, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { /* Magic number */ p += H5_SIZEOF_MAGIC; /* Version */ oh->version = *p++; if(H5O_VERSION_2 != oh->version) HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number") /* Flags */ oh->flags = *p++; if(oh->flags & ~H5O_HDR_ALL_FLAGS) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "unknown object header status flag(s)") /* Number of messages (to allocate initially) */ nmesgs = 1; /* Number of links to object (unless overridden by refcount message) */ oh->nlink = 1; /* Time fields */ if(oh->flags & H5O_HDR_STORE_TIMES) { uint32_t tmp; /* Temporary value */ UINT32DECODE(p, tmp); oh->atime = (time_t)tmp; UINT32DECODE(p, tmp); oh->mtime = (time_t)tmp; UINT32DECODE(p, tmp); oh->ctime = (time_t)tmp; UINT32DECODE(p, tmp); oh->btime = (time_t)tmp; } /* end if */ else oh->atime = oh->mtime = oh->ctime = oh->btime = 0; /* Attribute fields */ if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) { UINT16DECODE(p, oh->max_compact); UINT16DECODE(p, oh->min_dense); if(oh->max_compact < oh->min_dense) HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header attribute phase change values") } /* end if */
/*------------------------------------------------------------------------- * Function: H5G_obj_create * * Purpose: Create an object header for a group and update object location info * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Sep 29 2005 * *------------------------------------------------------------------------- */ herr_t H5G_obj_create(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo, const H5O_linfo_t *linfo, hid_t gcpl_id, H5O_loc_t *oloc/*out*/) { size_t hdr_size; /* Size of object header to request */ hbool_t use_latest_format; /* Flag indicating the new group format should be used */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_obj_create, FAIL) /* * Check arguments. */ HDassert(f); HDassert(ginfo); HDassert(oloc); /* Check for using the latest version of the group format */ /* (add more checks for creating "new format" groups when needed) */ if(H5F_USE_LATEST_FORMAT(f) || linfo->track_corder) use_latest_format = TRUE; else use_latest_format = FALSE; /* Make certain that the creation order is being tracked if an index is * going to be built on it. */ if(linfo->index_corder && !linfo->track_corder) HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "must track creation order to create index for it") /* Check if we should be using the latest version of the group format */ if(use_latest_format) { H5O_link_t lnk; /* Temporary link message info for computing message size */ char null_char = '\0'; /* Character for creating null string */ size_t ginfo_size; /* Size of the group info message */ size_t linfo_size; /* Size of the link info message */ size_t link_size; /* Size of a link message */ /* Calculate message size infomation, for creating group's object header */ linfo_size = H5O_msg_size_f(f, gcpl_id, H5O_LINFO_ID, linfo, (size_t)0); HDassert(linfo_size); ginfo_size = H5O_msg_size_f(f, gcpl_id, H5O_GINFO_ID, ginfo, (size_t)0); HDassert(ginfo_size); lnk.type = H5L_TYPE_HARD; lnk.corder = 0; lnk.corder_valid = linfo->track_corder; lnk.cset = H5T_CSET_ASCII; lnk.name = &null_char; link_size = H5O_msg_size_f(f, gcpl_id, H5O_LINK_ID, &lnk, (size_t)ginfo->est_name_len); HDassert(link_size); /* Compute size of header to use for creation */ hdr_size = linfo_size + ginfo_size + (ginfo->est_num_entries * link_size); } /* end if */ else hdr_size = 4 + 2 * H5F_SIZEOF_ADDR(f); /* * Create group's object header. It has a zero link count * since nothing refers to it yet. The link count will be * incremented if the object is added to the group directed graph. */ if(H5O_create(f, dxpl_id, hdr_size, gcpl_id, oloc/*out*/) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create header") /* Check for format of group to create */ if(use_latest_format) { /* Insert link info message */ if(H5O_msg_create(oloc, H5O_LINFO_ID, 0, 0, linfo, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message") /* Insert group info message */ if(H5O_msg_create(oloc, H5O_GINFO_ID, H5O_MSG_FLAG_CONSTANT, H5O_UPDATE_TIME, ginfo, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message") } /* end if */ else {
/*------------------------------------------------------------------------- * Function: H5F_read_superblock * * Purpose: Reads the superblock from the file or from the BUF. If * ADDR is a valid address, then it reads it from the file. * If not, then BUF must be non-NULL for it to read from the * BUF. * * Return: Success: SUCCEED * Failure: FAIL * * Programmer: Bill Wendling * [email protected] * Sept 12, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent) { haddr_t stored_eoa; /*relative end-of-addr in file */ haddr_t eof; /*end of file address */ uint8_t *q; /*ptr into temp I/O buffer */ size_t sizeof_addr = 0; size_t sizeof_size = 0; const size_t fixed_size = 24; /*fixed sizeof superblock */ unsigned sym_leaf_k = 0; size_t variable_size; /*variable sizeof superblock */ unsigned btree_k[H5B_NUM_BTREE_ID]; /* B-tree internal node 'K' values */ H5F_file_t *shared = NULL; /* shared part of `file' */ H5FD_t *lf = NULL; /* file driver part of `shared' */ uint8_t *p; /* Temporary pointer into encoding buffers */ unsigned i; /* Index variable */ unsigned chksum; /* Checksum temporary variable */ size_t driver_size; /* Size of driver info block, in bytes */ char driver_name[9]; /* Name of driver, for driver info block */ unsigned super_vers; /* Super block version */ unsigned freespace_vers; /* Freespace info version */ unsigned obj_dir_vers; /* Object header info version */ unsigned share_head_vers; /* Shared header info version */ uint8_t buf[H5F_SUPERBLOCK_SIZE]; /* Local buffer */ H5P_genplist_t *c_plist; /* File creation property list */ herr_t ret_value = SUCCEED; /* Decoding */ FUNC_ENTER_NOAPI(H5F_read_superblock, FAIL) /* Short cuts */ shared = f->shared; lf = shared->lf; /* Get the shared file creation property list */ if (NULL == (c_plist = H5I_object(shared->fcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") /* Read the superblock if it hasn't been read before. */ if (HADDR_UNDEF == (shared->super_addr=H5F_locate_signature(lf,dxpl_id))) HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to find file signature") if (H5FD_set_eoa(lf, shared->super_addr + fixed_size) < 0 || H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr, fixed_size, buf) < 0) HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "unable to read superblock") /* Signature, already checked */ p = buf + H5F_SIGNATURE_LEN; /* Superblock version */ super_vers = *p++; if (super_vers > HDF5_SUPERBLOCK_VERSION_MAX) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad superblock version number") if (H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set superblock version") /* Freespace version */ freespace_vers = *p++; if (HDF5_FREESPACE_VERSION != freespace_vers) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad free space version number") if (H5P_set(c_plist, H5F_CRT_FREESPACE_VERS_NAME, &freespace_vers) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to free space version") /* Root group version number */ obj_dir_vers = *p++; if (HDF5_OBJECTDIR_VERSION != obj_dir_vers) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad object directory version number") if (H5P_set(c_plist, H5F_CRT_OBJ_DIR_VERS_NAME, &obj_dir_vers) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set object directory version") /* Skip over reserved byte */ p++; /* Shared header version number */ share_head_vers = *p++; if (HDF5_SHAREDHEADER_VERSION != share_head_vers) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad shared-header format version number") if (H5P_set(c_plist, H5F_CRT_SHARE_HEAD_VERS_NAME, &share_head_vers) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set shared-header format version") /* Size of file addresses */ sizeof_addr = *p++; if (sizeof_addr != 2 && sizeof_addr != 4 && sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number in an address") if (H5P_set(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME,&sizeof_addr) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set byte number in an address") shared->sizeof_addr = sizeof_addr; /* Keep a local copy also */ /* Size of file sizes */ sizeof_size = *p++; if (sizeof_size != 2 && sizeof_size != 4 && sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number for object size") if (H5P_set(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set byte number for object size") shared->sizeof_size = sizeof_size; /* Keep a local copy also */ /* Skip over reserved byte */ p++; /* Various B-tree sizes */ UINT16DECODE(p, sym_leaf_k); if (sym_leaf_k == 0) HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "bad symbol table leaf node 1/2 rank") if (H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set rank for symbol table leaf nodes") shared->sym_leaf_k = sym_leaf_k; /* Keep a local copy also */ /* Need 'get' call to set other array values */ if (H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes") UINT16DECODE(p, btree_k[H5B_SNODE_ID]); if (btree_k[H5B_SNODE_ID] == 0) HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "bad 1/2 rank for btree internal nodes") /* * Delay setting the value in the property list until we've checked * for the indexed storage B-tree internal 'K' value later. */ /* File consistency flags. Not really used yet */ UINT32DECODE(p, shared->consist_flags); assert(((size_t)(p - buf)) == fixed_size); /* Decode the variable-length part of the superblock... */ variable_size = (super_vers>0 ? 4 : 0) + /* Potential indexed storage B-tree internal 'K' value */ H5F_SIZEOF_ADDR(f) + /*base addr*/ H5F_SIZEOF_ADDR(f) + /*global free list*/ H5F_SIZEOF_ADDR(f) + /*end-of-address*/ H5F_SIZEOF_ADDR(f) + /*reserved address*/ H5G_SIZEOF_ENTRY(f); /*root group ptr*/ assert(fixed_size + variable_size <= sizeof(buf)); if (H5FD_set_eoa(lf, shared->super_addr + fixed_size+variable_size) < 0 || H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr + fixed_size, variable_size, p) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read superblock") /* * If the superblock version # is greater than 0, read in the indexed * storage B-tree internal 'K' value */ if (super_vers > 0) { UINT16DECODE(p, btree_k[H5B_ISTORE_ID]); p += 2; /* reserved */ } else btree_k[H5B_ISTORE_ID] = HDF5_BTREE_ISTORE_IK_DEF; /* Set the B-tree internal node values, etc */ if (H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set rank for btree internal nodes") HDmemcpy(shared->btree_k, btree_k, sizeof(unsigned) * (size_t)H5B_NUM_BTREE_ID); /* Keep a local copy also */ H5F_addr_decode(f, (const uint8_t **)&p, &shared->base_addr/*out*/); H5F_addr_decode(f, (const uint8_t **)&p, &shared->freespace_addr/*out*/); H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/); H5F_addr_decode(f, (const uint8_t **)&p, &shared->driver_addr/*out*/); if (H5G_ent_decode(f, (const uint8_t **)&p, root_ent/*out*/) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read root symbol entry") /* * Check if superblock address is different from base address and * adjust base address and "end of address" address if so. */ if (!H5F_addr_eq(shared->super_addr,shared->base_addr)) { /* Check if the superblock moved earlier in the file */ if (H5F_addr_lt(shared->super_addr, shared->base_addr)) stored_eoa -= (shared->base_addr - shared->super_addr); else /* The superblock moved later in the file */ stored_eoa += (shared->super_addr - shared->base_addr); shared->base_addr = shared->super_addr; } /* end if */ /* Compute super block checksum */ assert(sizeof(chksum) == sizeof(shared->super_chksum)); for (q = (uint8_t *)&chksum, chksum = 0, i = 0; i < fixed_size + variable_size; ++i) q[i % sizeof(shared->super_chksum)] ^= buf[i]; /* Set the super block checksum */ shared->super_chksum = chksum; /* Decode the optional driver information block */ if (H5F_addr_defined(shared->driver_addr)) { haddr_t drv_addr = shared->base_addr + shared->driver_addr; uint8_t dbuf[H5F_DRVINFOBLOCK_SIZE]; /* Local buffer */ if (H5FD_set_eoa(lf, drv_addr + 16) < 0 || H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr, (size_t)16, dbuf) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read driver information block") p = dbuf; /* Version number */ if (HDF5_DRIVERINFO_VERSION != *p++) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "bad driver information block version number") p += 3; /* reserved */ /* Driver info size */ UINT32DECODE(p, driver_size); /* Driver name and/or version */ HDstrncpy(driver_name, (const char *)p, (size_t)8); driver_name[8] = '\0'; p += 8; /* advance past name/version */ /* Read driver information and decode */ assert((driver_size + 16) <= sizeof(dbuf)); if (H5FD_set_eoa(lf, drv_addr + 16 + driver_size) < 0 || H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr+16, driver_size, p) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read file driver information") if (H5FD_sb_decode(lf, driver_name, p) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to decode driver information") /* Compute driver info block checksum */ assert(sizeof(chksum) == sizeof(shared->drvr_chksum)); for (q = (uint8_t *)&chksum, chksum = 0, i = 0; i < (driver_size + 16); ++i) q[i % sizeof(shared->drvr_chksum)] ^= dbuf[i]; /* Set the driver info block checksum */ shared->drvr_chksum = chksum; } /* end if */