/*------------------------------------------------------------------------- * Function: H5G__create * * Purpose: Creates a new empty group with the specified name. The name * is either an absolute name or is relative to LOC. * * Return: Success: A handle for the group. The group is opened * and should eventually be close by calling * H5G_close(). * * Failure: NULL * * Programmer: Robb Matzke * [email protected] * Aug 11 1997 * *------------------------------------------------------------------------- */ H5G_t * H5G__create(H5F_t *file, H5G_obj_create_t *gcrt_info, hid_t dxpl_id) { H5G_t *grp = NULL; /*new group */ unsigned oloc_init = 0; /* Flag to indicate that the group object location was created successfully */ H5G_t *ret_value = NULL; /* Return value */ FUNC_ENTER_PACKAGE /* check args */ HDassert(file); HDassert(gcrt_info->gcpl_id != H5P_DEFAULT); HDassert(dxpl_id != H5P_DEFAULT); /* create an open group */ if(NULL == (grp = H5FL_CALLOC(H5G_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") if(NULL == (grp->shared = H5FL_CALLOC(H5G_shared_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Create the group object header */ if(H5G__obj_create(file, dxpl_id, gcrt_info, &(grp->oloc)/*out*/) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "unable to create group object header") oloc_init = 1; /* Indicate that the object location information is valid */ /* Add group to list of open objects in file */ if(H5FO_top_incr(grp->oloc.file, grp->oloc.addr) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINC, NULL, "can't incr object ref. count") if(H5FO_insert(grp->oloc.file, grp->oloc.addr, grp->shared, TRUE) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group into list of open objects") /* Set the count of times the object is opened */ grp->shared->fo_count = 1; /* Set return value */ ret_value = grp; done: if(ret_value == NULL) { /* Check if we need to release the file-oriented symbol table info */ if(oloc_init) { if(H5O_dec_rc_by_loc(&(grp->oloc), dxpl_id) < 0) HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, "unable to decrement refcount on newly created object") if(H5O_close(&(grp->oloc)) < 0) HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "unable to release object header") if(H5O_delete(file, dxpl_id, grp->oloc.addr) < 0) HDONE_ERROR(H5E_SYM, H5E_CANTDELETE, NULL, "unable to delete object header") } /* end if */ if(grp != NULL) { if(grp->shared != NULL) grp->shared = H5FL_FREE(H5G_shared_t, grp->shared); grp = H5FL_FREE(H5G_t, grp); } /* end if */ } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5G__create() */
/*------------------------------------------------------------------------- * Function: H5D_mpio_spaces_xfer * * Purpose: Use MPI-IO to transfer data efficiently * directly between app buffer and file. * * Return: non-negative on success, negative on failure. * * Programmer: rky 980813 * * Notes: * For collective data transfer only since this would eventually call * H5FD_mpio_setup to do setup to eveually call MPI_File_set_view in * H5FD_mpio_read or H5FD_mpio_write. MPI_File_set_view is a collective * call. Letting independent data transfer use this route would result in * hanging. * * The preconditions for calling this routine are located in the * H5S_mpio_opt_possible() routine, which determines whether this routine * can be called for a given dataset transfer. * * Modifications: * rky 980918 * Added must_convert parameter to let caller know we can't optimize * the xfer. * * Albert Cheng, 001123 * Include the MPI_type freeing as part of cleanup code. * * QAK - 2002/04/02 * Removed the must_convert parameter and move preconditions to * H5S_mpio_opt_possible() routine * * QAK - 2002/06/17 * Removed 'disp' parameter from H5FD_mpio_setup routine and use the * address of the dataset in MPI_File_set_view() calls, as necessary. * * QAK - 2002/06/18 * Removed 'dc_plist' parameter, since it was not used. Also, switch to * getting the 'extra_offset' setting for each selection. * *------------------------------------------------------------------------- */ static herr_t H5D_mpio_spaces_xfer(H5D_io_info_t *io_info, size_t elmt_size, const H5S_t *file_space, const H5S_t *mem_space, void *_buf /*out*/, hbool_t do_write ) { haddr_t addr; /* Address of dataset (or selection) within file */ size_t mpi_buf_count, mpi_file_count; /* Number of "objects" to transfer */ hsize_t mpi_buf_offset, mpi_file_offset; /* Offset within dataset where selection (ie. MPI type) begins */ MPI_Datatype mpi_buf_type, mpi_file_type; /* MPI types for buffer (memory) and file */ hbool_t mbt_is_derived=0, /* Whether the buffer (memory) type is derived and needs to be free'd */ mft_is_derived=0; /* Whether the file type is derived and needs to be free'd */ hbool_t plist_is_setup=0; /* Whether the dxpl has been customized */ uint8_t *buf=(uint8_t *)_buf; /* Alias for pointer arithmetic */ int mpi_code; /* MPI return code */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_spaces_xfer); /* Check args */ assert (io_info); assert (io_info->dset); assert (file_space); assert (mem_space); assert (buf); assert (IS_H5FD_MPIO(io_info->dset->ent.file)); /* Make certain we have the correct type of property list */ assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER)); /* create the MPI buffer type */ if (H5S_mpio_space_type( mem_space, elmt_size, /* out: */ &mpi_buf_type, &mpi_buf_count, &mpi_buf_offset, &mbt_is_derived )<0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't create MPI buf type"); /* create the MPI file type */ if ( H5S_mpio_space_type( file_space, elmt_size, /* out: */ &mpi_file_type, &mpi_file_count, &mpi_file_offset, &mft_is_derived )<0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't create MPI file type"); /* Get the base address of the contiguous dataset or the chunk */ if(io_info->dset->shared->layout.type == H5D_CONTIGUOUS) addr = H5D_contig_get_addr(io_info->dset) + mpi_file_offset; else { haddr_t chunk_addr; /* for collective chunk IO */ assert(io_info->dset->shared->layout.type == H5D_CHUNKED); chunk_addr=H5D_istore_get_addr(io_info,NULL); addr = H5F_BASE_ADDR(io_info->dset->ent.file) + chunk_addr + mpi_file_offset; } /* * Pass buf type, file type to the file driver. Request an MPI type * transfer (instead of an elementary byteblock transfer). */ if(H5FD_mpi_setup_collective(io_info->dxpl_id, mpi_buf_type, mpi_file_type)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI-I/O properties"); plist_is_setup=1; /* Adjust the buffer pointer to the beginning of the selection */ buf+=mpi_buf_offset; /* transfer the data */ if (do_write) { if (H5F_block_write(io_info->dset->ent.file, H5FD_MEM_DRAW, addr, mpi_buf_count, io_info->dxpl_id, buf) <0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL,"MPI write failed"); } else { if (H5F_block_read (io_info->dset->ent.file, H5FD_MEM_DRAW, addr, mpi_buf_count, io_info->dxpl_id, buf) <0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL,"MPI read failed"); } done: /* Reset the dxpl settings */ if(plist_is_setup) { if(H5FD_mpi_teardown_collective(io_info->dxpl_id)<0) HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "unable to reset dxpl values"); } /* end if */ /* free the MPI buf and file types */ if (mbt_is_derived) { if (MPI_SUCCESS != (mpi_code= MPI_Type_free( &mpi_buf_type ))) HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code); } if (mft_is_derived) { if (MPI_SUCCESS != (mpi_code= MPI_Type_free( &mpi_file_type ))) HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code); } FUNC_LEAVE_NOAPI(ret_value); } /* end H5D_mpio_spaces_xfer() */
/*------------------------------------------------------------------------- * Function: H5S_mpio_hyper_type * * Purpose: Translate an HDF5 hyperslab selection into an MPI type. * * Return: non-negative on success, negative on failure. * * Outputs: *new_type the MPI type corresponding to the selection * *count how many objects of the new_type in selection * (useful if this is the buffer type for xfer) * *extra_offset Number of bytes of offset within dataset * *is_derived_type 0 if MPI primitive type, 1 if derived * * Programmer: rky 980813 * * Modifications: ppw 990401 * rky, ppw 2000-09-26 Freed old type after creating struct type. * rky 2000-10-05 Changed displacements to be MPI_Aint. * rky 2000-10-06 Added code for cases of empty hyperslab. * akc, rky 2000-11-16 Replaced hard coded dimension size with * H5S_MAX_RANK. * * Quincey Koziol, June 18, 2002 * Added 'extra_offset' parameter. Also accomodate selection * offset in MPI type built. * * Albert Cheng, August 4, 2004 * Reimplemented the algorithm of forming the outer_type by * defining it as (start, vector, extent) in one call. * *------------------------------------------------------------------------- */ static herr_t H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, /* out: */ MPI_Datatype *new_type, size_t *count, hsize_t *extra_offset, hbool_t *is_derived_type ) { H5S_sel_iter_t sel_iter; /* Selection iteration info */ hbool_t sel_iter_init=0; /* Selection iteration info has been initialized */ struct dim { /* less hassle than malloc/free & ilk */ hssize_t start; hsize_t strid; hsize_t block; hsize_t xtent; hsize_t count; } d[H5S_MAX_RANK]; int i; int offset[H5S_MAX_RANK]; int max_xtent[H5S_MAX_RANK]; H5S_hyper_dim_t *diminfo; /* [rank] */ int rank; int block_length[3]; MPI_Datatype inner_type, outer_type, old_types[3]; MPI_Aint extent_len, displacement[3]; int mpi_code; /* MPI return code */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_hyper_type); /* Check args */ assert (space); assert(sizeof(MPI_Aint) >= sizeof(elmt_size)); if (0==elmt_size) goto empty; /* Initialize selection iterator */ if (H5S_select_iter_init(&sel_iter, space, elmt_size)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); sel_iter_init=1; /* Selection iteration info has been initialized */ /* Abbreviate args */ diminfo=sel_iter.u.hyp.diminfo; assert (diminfo); /* make a local copy of the dimension info so we can operate with them */ /* Check if this is a "flattened" regular hyperslab selection */ if(sel_iter.u.hyp.iter_rank!=0 && sel_iter.u.hyp.iter_rank<space->extent.rank) { /* Flattened selection */ rank=sel_iter.u.hyp.iter_rank; assert (rank >= 0 && rank<=H5S_MAX_RANK); /* within array bounds */ if (0==rank) goto empty; #ifdef H5S_DEBUG if(H5DEBUG(S)) HDfprintf(H5DEBUG(S), "%s: Flattened selection\n",FUNC); #endif for ( i=0; i<rank; ++i) { d[i].start = diminfo[i].start+sel_iter.u.hyp.sel_off[i]; d[i].strid = diminfo[i].stride; d[i].block = diminfo[i].block; d[i].count = diminfo[i].count; d[i].xtent = sel_iter.u.hyp.size[i]; #ifdef H5S_DEBUG if(H5DEBUG(S)){ HDfprintf(H5DEBUG(S), "%s: start=%Hd stride=%Hu count=%Hu block=%Hu xtent=%Hu", FUNC, d[i].start, d[i].strid, d[i].count, d[i].block, d[i].xtent ); if (i==0) HDfprintf(H5DEBUG(S), " rank=%d\n", rank ); else HDfprintf(H5DEBUG(S), "\n" ); } #endif if (0==d[i].block) goto empty; if (0==d[i].count) goto empty; if (0==d[i].xtent) goto empty; } } /* end if */ else { /* Non-flattened selection */ rank = space->extent.rank; assert (rank >= 0 && rank<=H5S_MAX_RANK); /* within array bounds */ if (0==rank) goto empty; #ifdef H5S_DEBUG if(H5DEBUG(S)) HDfprintf(H5DEBUG(S),"%s: Non-flattened selection\n",FUNC); #endif for ( i=0; i<rank; ++i) { d[i].start = diminfo[i].start+space->select.offset[i]; d[i].strid = diminfo[i].stride; d[i].block = diminfo[i].block; d[i].count = diminfo[i].count; d[i].xtent = space->extent.size[i]; #ifdef H5S_DEBUG if(H5DEBUG(S)){ HDfprintf(H5DEBUG(S), "%s: start=%Hd stride=%Hu count=%Hu block=%Hu xtent=%Hu", FUNC, d[i].start, d[i].strid, d[i].count, d[i].block, d[i].xtent ); if (i==0) HDfprintf(H5DEBUG(S), " rank=%d\n", rank ); else HDfprintf(H5DEBUG(S), "\n" ); } #endif if (0==d[i].block) goto empty; if (0==d[i].count) goto empty; if (0==d[i].xtent) goto empty; } } /* end else */ /********************************************************************** Compute array "offset[rank]" which gives the offsets for a multi- dimensional array with dimensions "d[i].xtent" (i=0,1,...,rank-1). **********************************************************************/ offset[rank-1] = 1; max_xtent[rank-1] = d[rank-1].xtent; /*#ifdef H5Smpi_DEBUG */ /* leave the old way */ #ifdef H5S_DEBUG if(H5DEBUG(S)){ i=rank-1; HDfprintf(H5DEBUG(S), " offset[%2d]=%d; max_xtent[%2d]=%d\n", i, offset[i], i, max_xtent[i]); } #endif for (i=rank-2; i>=0; --i) { offset[i] = offset[i+1]*d[i+1].xtent; max_xtent[i] = max_xtent[i+1]*d[i].xtent; #ifdef H5S_DEBUG if(H5DEBUG(S)){ HDfprintf(H5DEBUG(S), " offset[%2d]=%d; max_xtent[%2d]=%d\n", i, offset[i], i, max_xtent[i]); } #endif } /* Create a type covering the selected hyperslab. * Multidimensional dataspaces are stored in row-major order. * The type is built from the inside out, going from the * fastest-changing (i.e., inner) dimension * to the slowest (outer). */ /******************************************************* * Construct contig type for inner contig dims: *******************************************************/ #ifdef H5S_DEBUG if(H5DEBUG(S)) { HDfprintf(H5DEBUG(S), "%s: Making contig type %d MPI_BYTEs\n", FUNC,elmt_size ); for (i=rank-1; i>=0; --i) HDfprintf(H5DEBUG(S), "d[%d].xtent=%Hu \n", i, d[i].xtent); } #endif if (MPI_SUCCESS != (mpi_code= MPI_Type_contiguous( (int)elmt_size, MPI_BYTE, &inner_type ))) HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code); /******************************************************* * Construct the type by walking the hyperslab dims * from the inside out: *******************************************************/ for ( i=rank-1; i>=0; --i) { #ifdef H5S_DEBUG if(H5DEBUG(S)) { HDfprintf(H5DEBUG(S), "%s: Dimension i=%d \n" "start=%Hd count=%Hu block=%Hu stride=%Hu, xtent=%Hu max_xtent=%d\n", FUNC, i, d[i].start, d[i].count, d[i].block, d[i].strid, d[i].xtent, max_xtent[i]); } #endif #ifdef H5S_DEBUG if(H5DEBUG(S)) HDfprintf(H5DEBUG(S), "%s: i=%d Making vector-type \n", FUNC,i); #endif /**************************************** * Build vector type of the selection. ****************************************/ mpi_code =MPI_Type_vector((int)(d[i].count), /* count */ (int)(d[i].block), /* blocklength */ (int)(d[i].strid), /* stride */ inner_type, /* old type */ &outer_type); /* new type */ MPI_Type_free( &inner_type ); if (mpi_code!=MPI_SUCCESS) HMPI_GOTO_ERROR(FAIL, "couldn't create MPI vector type", mpi_code); /**************************************** * Then build the dimension type as (start, vector type, xtent). ****************************************/ /* calculate start and extent values of this dimension */ displacement[1] = d[i].start * offset[i] * elmt_size; displacement[2] = (MPI_Aint)elmt_size * max_xtent[i]; if(MPI_SUCCESS != (mpi_code = MPI_Type_extent(outer_type, &extent_len))) HMPI_GOTO_ERROR(FAIL, "MPI_Type_extent failed", mpi_code); /************************************************* * Restructure this datatype ("outer_type") * so that it still starts at 0, but its extent * is the full extent in this dimension. *************************************************/ if (displacement[1] > 0 || (int)extent_len < displacement[2]) { block_length[0] = 1; block_length[1] = 1; block_length[2] = 1; displacement[0] = 0; old_types[0] = MPI_LB; old_types[1] = outer_type; old_types[2] = MPI_UB; #ifdef H5S_DEBUG if(H5DEBUG(S)){ HDfprintf(H5DEBUG(S), "%s: i=%d Extending struct type\n" "***displacements: %d, %d, %d\n", FUNC, i, displacement[0], displacement[1], displacement[2]); } #endif mpi_code = MPI_Type_struct ( 3, /* count */ block_length, /* blocklengths */ displacement, /* displacements */ old_types, /* old types */ &inner_type); /* new type */ MPI_Type_free (&outer_type); if (mpi_code!=MPI_SUCCESS) HMPI_GOTO_ERROR(FAIL, "couldn't resize MPI vector type", mpi_code); } else { inner_type = outer_type; } } /* end for */ /*************************** * End of loop, walking * thru dimensions. ***************************/ /* At this point inner_type is actually the outermost type, even for 0-trip loop */ *new_type = inner_type; if (MPI_SUCCESS != (mpi_code= MPI_Type_commit( new_type ))) HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); /* fill in the remaining return values */ *count = 1; /* only have to move one of these suckers! */ *extra_offset = 0; *is_derived_type = 1; HGOTO_DONE(SUCCEED); empty: /* special case: empty hyperslab */ *new_type = MPI_BYTE; *count = 0; *extra_offset = 0; *is_derived_type = 0; done: /* Release selection iterator */ if(sel_iter_init) { if (H5S_SELECT_ITER_RELEASE(&sel_iter)<0) HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ #ifdef H5S_DEBUG if(H5DEBUG(S)){ HDfprintf(H5DEBUG(S), "Leave %s, count=%ld is_derived_type=%d\n", FUNC, *count, *is_derived_type ); } #endif FUNC_LEAVE_NOAPI(ret_value); }
/*------------------------------------------------------------------------- * Function: H5FS_create * * Purpose: Allocate & initialize file free space info * * Return: Success: Pointer to free space structure * * Failure: NULL * * Programmer: Quincey Koziol * Tuesday, March 7, 2006 * * Modifications: * Vailin Choi, July 29th, 2008 * Add two more parameters for handling alignment: alignment & threshhold * *------------------------------------------------------------------------- */ H5FS_t * H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_create, size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold) { H5FS_t *fspace = NULL; /* New free space structure */ H5FS_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_TAG(dxpl_id, H5AC__FREESPACE_TAG, NULL) #ifdef H5FS_DEBUG HDfprintf(stderr, "%s: Creating free space manager, nclasses = %Zu\n", FUNC, nclasses); #endif /* H5FS_DEBUG */ /* Check arguments. */ HDassert(fs_create->shrink_percent); HDassert(fs_create->shrink_percent < fs_create->expand_percent); HDassert(fs_create->max_sect_size); HDassert(nclasses == 0 || classes); /* * Allocate free space structure */ if(NULL == (fspace = H5FS_new(f, nclasses, classes, cls_init_udata))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space free list") /* Initialize creation information for free space manager */ fspace->client = fs_create->client; fspace->shrink_percent = fs_create->shrink_percent; fspace->expand_percent = fs_create->expand_percent; fspace->max_sect_addr = fs_create->max_sect_addr; fspace->max_sect_size = fs_create->max_sect_size; fspace->alignment = alignment; fspace->threshold = threshold; /* Check if the free space tracker is supposed to be persistant */ if(fs_addr) { /* Allocate space for the free space header */ if(HADDR_UNDEF == (fspace->addr = H5MF_alloc(f, H5FD_MEM_FSPACE_HDR, dxpl_id, (hsize_t)fspace->hdr_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for free space header") /* Cache the new free space header (pinned) */ if(H5AC_insert_entry(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, fspace, H5AC__PIN_ENTRY_FLAG) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space header to cache") /* Return free space header address to caller, if desired */ *fs_addr = fspace->addr; } /* end if */ /* Set the reference count to 1, since we inserted the entry in the cache pinned */ fspace->rc = 1; /* Set the return value */ ret_value = fspace; #ifdef H5FS_DEBUG HDfprintf(stderr, "%s: fspace = %p, fspace->addr = %a\n", FUNC, fspace, fspace->addr); #endif /* H5FS_DEBUG */ done: if(!ret_value && fspace) if(H5FS_hdr_dest(fspace) < 0) HDONE_ERROR(H5E_FSPACE, H5E_CANTFREE, NULL, "unable to destroy free space header") #ifdef H5FS_DEBUG HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value); #endif /* H5FS_DEBUG */ FUNC_LEAVE_NOAPI_TAG(ret_value, NULL) } /* H5FS_create() */
/*------------------------------------------------------------------------- * Function: H5HL_debug * * Purpose: Prints debugging information about a heap. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * [email protected] * Aug 1 1997 * * Modifications: * Robb Matzke, 1999-07-28 * The ADDR argument is passed by value. * * John Mainzer, 6/17/05 * Modified the function to use the new dirtied parameter of * of H5AC_unprotect() instead of modifying the is_dirty * field of the cache info. * *------------------------------------------------------------------------- */ herr_t H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int fwidth) { H5HL_t *h = NULL; int i, overlap, free_block; H5HL_free_t *freelist = NULL; uint8_t *marker = NULL; size_t amount_free = 0; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HL_debug, FAIL) /* check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); HDassert(stream); HDassert(indent >= 0); HDassert(fwidth >= 0); if(NULL == (h = (H5HL_t *)H5HL_protect(f, dxpl_id, addr, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") fprintf(stream, "%*sLocal Heap...\n", indent, ""); fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, "Header size (in bytes):", (unsigned long)h->prfx_size); HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, "Address of heap data:", h->dblk_addr); HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, "Data bytes allocated for heap:", h->dblk_size); /* * Traverse the free list and check that all free blocks fall within * the heap and that no two free blocks point to the same region of * the heap. */ if(NULL == (marker = (uint8_t *)H5MM_calloc(h->dblk_size))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "memory allocation failed") fprintf(stream, "%*sFree Blocks (offset, size):\n", indent, ""); for(free_block = 0, freelist = h->freelist; freelist; freelist = freelist->next, free_block++) { char temp_str[32]; sprintf(temp_str,"Block #%d:",free_block); HDfprintf(stream, "%*s%-*s %8Zu, %8Zu\n", indent+3, "", MAX(0,fwidth-9), temp_str, freelist->offset, freelist->size); if((freelist->offset + freelist->size) > h->dblk_size) fprintf(stream, "***THAT FREE BLOCK IS OUT OF BOUNDS!\n"); else { for(i = overlap = 0; i < (int)(freelist->size); i++) { if(marker[freelist->offset + i]) overlap++; marker[freelist->offset + i] = 1; } /* end for */ if(overlap) fprintf(stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS ONE!\n"); else amount_free += freelist->size; } /* end for */ } /* end for */ if(h->dblk_size) fprintf(stream, "%*s%-*s %.2f%%\n", indent, "", fwidth, "Percent of heap used:", (100.0 * (double)(h->dblk_size - amount_free) / (double)h->dblk_size)); /* * Print the data in a VMS-style octal dump. */ H5_buffer_dump(stream, indent, h->dblk_image, marker, (size_t)0, h->dblk_size); done: if(h && H5HL_unprotect(h) < 0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") H5MM_xfree(marker); FUNC_LEAVE_NOAPI(ret_value) } /* end H5HL_debug() */
/*------------------------------------------------------------------------- * 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 */
/*-------------------------------------------------------------------------- NAME H5O_attr_decode PURPOSE Decode a attribute message and return a pointer to a memory struct with the decoded information USAGE void *H5O_attr_decode(f, raw_size, p) H5F_t *f; IN: pointer to the HDF5 file struct size_t raw_size; IN: size of the raw information buffer const uint8_t *p; IN: the raw information buffer RETURNS Pointer to the new message in native order on success, NULL on failure DESCRIPTION This function decodes the "raw" disk form of a attribute message into a struct in memory native format. The struct is allocated within this function using malloc() and is returned to the caller. --------------------------------------------------------------------------*/ static void * H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p) { H5A_t *attr = NULL; H5S_extent_t *extent; /*extent dimensionality information */ size_t name_len; /*attribute name length */ int version; /*message version number*/ unsigned flags = 0; /* Attribute flags */ H5A_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_decode); /* check args */ HDassert(f); HDassert(p); if(NULL == (attr = H5FL_CALLOC(H5A_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Version number */ version = *p++; if (version!=H5O_ATTR_VERSION && version!=H5O_ATTR_VERSION_NEW) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for attribute message"); /* Get the flags byte if we have a later version of the attribute */ if(version>H5O_ATTR_VERSION) flags = *p++; else p++; /* Byte is unused when version<2 */ /* * Decode the sizes of the parts of the attribute. The sizes stored in * the file are exact but the parts are aligned on 8-byte boundaries. */ UINT16DECODE(p, name_len); /*including null*/ UINT16DECODE(p, attr->dt_size); UINT16DECODE(p, attr->ds_size); /* Decode and store the name */ if (NULL==(attr->name=H5MM_strdup((const char *)p))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); if(version < H5O_ATTR_VERSION_NEW) p += H5O_ALIGN(name_len); /* advance the memory pointer */ else p += name_len; /* advance the memory pointer */ /* decode the attribute datatype */ if (flags & H5O_ATTR_FLAG_TYPE_SHARED) { H5O_shared_t *shared; /* Shared information */ /* Get the shared information */ if (NULL == (shared = (H5O_MSG_SHARED->decode) (f, dxpl_id, p))) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode shared message"); /* Get the actual datatype information */ if((attr->dt= H5O_shared_read(f, dxpl_id, shared, H5O_MSG_DTYPE, NULL))==NULL) HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype"); /* Free the shared information */ H5O_free_real(H5O_MSG_SHARED, shared); } /* end if */ else { if((attr->dt=(H5O_MSG_DTYPE->decode)(f,dxpl_id,p))==NULL) HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype"); } /* end else */ if(version < H5O_ATTR_VERSION_NEW) p += H5O_ALIGN(attr->dt_size); else p += attr->dt_size; /* decode the attribute dataspace */ if (NULL==(attr->ds = H5FL_CALLOC(H5S_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); if((extent=(H5O_MSG_SDSPACE->decode)(f,dxpl_id,p))==NULL) HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace"); /* Copy the extent information */ HDmemcpy(&(attr->ds->extent),extent, sizeof(H5S_extent_t)); /* Release temporary extent information */ H5FL_FREE(H5S_extent_t,extent); /* Default to entire dataspace being selected */ if(H5S_select_all(attr->ds, 0) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection") if(version < H5O_ATTR_VERSION_NEW) p += H5O_ALIGN(attr->ds_size); else p += attr->ds_size; /* Compute the size of the data */ H5_ASSIGN_OVERFLOW(attr->data_size,H5S_GET_EXTENT_NPOINTS(attr->ds)*H5T_get_size(attr->dt),hsize_t,size_t); /* Go get the data */ if(attr->data_size) { if (NULL==(attr->data = H5FL_BLK_MALLOC(attr_buf, attr->data_size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); HDmemcpy(attr->data,p,attr->data_size); } /* Indicate that the fill values aren't to be written out */ attr->initialized=1; /* Set return value */ ret_value = attr; done: if(!ret_value) if(attr) { /* Free dynamicly allocated items */ if(H5A_free(attr) < 0) HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't release attribute info") H5FL_FREE(H5A_t, attr); } /* end if */ FUNC_LEAVE_NOAPI(ret_value); }
/*------------------------------------------------------------------------- * Function: H5O_efl_copy_file * * Purpose: Copies an efl message from _MESG to _DEST in file * * Return: Success: Ptr to _DEST * * Failure: NULL * * Programmer: Peter Cao * September 29, 2005 * *------------------------------------------------------------------------- */ static void * H5O_efl_copy_file(H5F_t H5_ATTR_UNUSED *file_src, void *mesg_src, H5F_t *file_dst, hbool_t H5_ATTR_UNUSED *recompute_size, unsigned H5_ATTR_UNUSED *mesg_flags, H5O_copy_t H5_ATTR_UNUSED *cpy_info, void H5_ATTR_UNUSED *_udata, hid_t dxpl_id) { H5O_efl_t *efl_src = (H5O_efl_t *) mesg_src; H5O_efl_t *efl_dst = NULL; H5HL_t *heap = NULL; /* Pointer to local heap for EFL file names */ size_t idx, size, name_offset, heap_size; void *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_TAG(dxpl_id, H5AC__COPIED_TAG, NULL) /* check args */ HDassert(efl_src); HDassert(file_dst); /* Allocate space for the destination efl */ if(NULL == (efl_dst = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Copy the "top level" information */ HDmemcpy(efl_dst, efl_src, sizeof(H5O_efl_t)); /* Determine size needed for destination heap */ heap_size = H5HL_ALIGN(1); /* "empty" name */ for(idx = 0; idx < efl_src->nused; idx++) heap_size += H5HL_ALIGN(HDstrlen(efl_src->slot[idx].name) + 1); /* Create name heap */ if(H5HL_create(file_dst, dxpl_id, heap_size, &efl_dst->heap_addr/*out*/) < 0) HGOTO_ERROR(H5E_EFL, H5E_CANTINIT, NULL, "can't create heap") /* Pin the heap down in memory */ if(NULL == (heap = H5HL_protect(file_dst, dxpl_id, efl_dst->heap_addr, H5AC__NO_FLAGS_SET))) HGOTO_ERROR(H5E_EFL, H5E_PROTECT, NULL, "unable to protect EFL file name heap") /* Insert "empty" name first */ if((size_t)(-1) == (name_offset = H5HL_insert(file_dst, dxpl_id, heap, (size_t)1, ""))) HGOTO_ERROR(H5E_EFL, H5E_CANTINSERT, NULL, "can't insert file name into heap") HDassert(0 == name_offset); /* allocate array of external file entries */ if(efl_src->nalloc > 0) { size = efl_src->nalloc * sizeof(H5O_efl_entry_t); if((efl_dst->slot = (H5O_efl_entry_t *)H5MM_calloc(size)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* copy content from the source. Need to update later */ HDmemcpy(efl_dst->slot, efl_src->slot, size); } /* end if */ /* copy the name from the source */ for(idx = 0; idx < efl_src->nused; idx++) { efl_dst->slot[idx].name = H5MM_xstrdup(efl_src->slot[idx].name); if((size_t)(-1) == (efl_dst->slot[idx].name_offset = H5HL_insert(file_dst, dxpl_id, heap, HDstrlen(efl_dst->slot[idx].name) + 1, efl_dst->slot[idx].name))) HGOTO_ERROR(H5E_EFL, H5E_CANTINSERT, NULL, "can't insert file name into heap") } /* end for */ /* Set return value */ ret_value = efl_dst; done: /* Release resources */ if(heap && H5HL_unprotect(heap) < 0) HDONE_ERROR(H5E_EFL, H5E_PROTECT, NULL, "unable to unprotect EFL file name heap") if(!ret_value) if(efl_dst) H5MM_xfree(efl_dst); FUNC_LEAVE_NOAPI_TAG(ret_value, NULL) } /* end H5O_efl_copy_file() */
/*------------------------------------------------------------------------- * Function: H5HG_debug * * Purpose: Prints debugging information about a global heap collection. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * [email protected] * Mar 27, 1998 * *------------------------------------------------------------------------- */ herr_t H5HG_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth) { unsigned u, nused, maxobj; unsigned j, k; H5HG_heap_t *h = NULL; uint8_t *p = NULL; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* check arguments */ HDassert(f); HDassert(H5F_addr_defined (addr)); HDassert(stream); HDassert(indent >= 0); HDassert(fwidth >= 0); if(NULL == (h = H5HG_protect(f, dxpl_id, addr, H5AC__READ_ONLY_FLAG))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect global heap collection"); HDfprintf(stream, "%*sGlobal Heap Collection...\n", indent, ""); HDfprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, "Dirty:", (int)(h->cache_info.is_dirty)); HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, "Total collection size in file:", (unsigned long)(h->size)); for(u = 1, nused = 0, maxobj = 0; u < h->nused; u++) if(h->obj[u].begin) { nused++; if (u>maxobj) maxobj = u; } HDfprintf(stream, "%*s%-*s %u/%lu/", indent, "", fwidth, "Objects defined/allocated/max:", nused, (unsigned long)h->nalloc); if(nused) HDfprintf(stream, "%u\n", maxobj); else HDfprintf(stream, "NA\n"); HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, "Free space:", (unsigned long)(h->obj[0].size)); for(u = 1; u < h->nused; u++) if(h->obj[u].begin) { char buf[64]; HDsnprintf(buf, sizeof(buf), "Object %u", u); HDfprintf(stream, "%*s%s\n", indent, "", buf); HDfprintf(stream, "%*s%-*s %lu\n", indent + 3, "", MIN(fwidth - 3, 0), "Obffset in block:", (unsigned long)(h->obj[u].begin - h->chunk)); HDfprintf(stream, "%*s%-*s %d\n", indent + 3, "", MIN(fwidth - 3, 0), "Reference count:", h->obj[u].nrefs); HDfprintf(stream, "%*s%-*s %lu/%lu\n", indent + 3, "", MIN(fwidth - 3, 0), "Size of object body:", (unsigned long)(h->obj[u].size), (unsigned long)H5HG_ALIGN(h->obj[u].size)); p = h->obj[u].begin + H5HG_SIZEOF_OBJHDR(f); for(j = 0; j < h->obj[u].size; j += 16) { HDfprintf(stream, "%*s%04u: ", indent + 6, "", j); for(k = 0; k < 16; k++) { if(8 == k) HDfprintf(stream, " "); if(j + k < h->obj[u].size) HDfprintf(stream, "%02x ", p[j + k]); else HDfputs(" ", stream); } for(k = 0; k < 16 && j + k < h->obj[u].size; k++) { if(8 == k) HDfprintf(stream, " "); HDfputc(p[j + k]>' ' && p[j + k] <= '~' ? p[j + k] : '.', stream); } HDfprintf(stream, "\n"); } } done: if (h && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, addr, h, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); } /* end H5HG_debug() */
/*------------------------------------------------------------------------- * Function: H5HL_debug * * Purpose: Prints debugging information about a heap. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * [email protected] * Aug 1 1997 * * Modifications: * Robb Matzke, 1999-07-28 * The ADDR argument is passed by value. *------------------------------------------------------------------------- */ herr_t H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int fwidth) { H5HL_t *h = NULL; int i, j, overlap, free_block; uint8_t c; H5HL_free_t *freelist = NULL; uint8_t *marker = NULL; size_t amount_free = 0; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HL_debug, FAIL); /* check arguments */ assert(f); assert(H5F_addr_defined(addr)); assert(stream); assert(indent >= 0); assert(fwidth >= 0); if (NULL == (h = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap"); fprintf(stream, "%*sLocal Heap...\n", indent, ""); fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, "Dirty:", (int) (h->cache_info.is_dirty)); fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, "Header size (in bytes):", (unsigned long) H5HL_SIZEOF_HDR(f)); HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, "Address of heap data:", h->addr); HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, "Data bytes allocated on disk:", h->disk_alloc); HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, "Data bytes allocated in core:", h->mem_alloc); /* * Traverse the free list and check that all free blocks fall within * the heap and that no two free blocks point to the same region of * the heap. */ if (NULL==(marker = H5MM_calloc(h->mem_alloc))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); fprintf(stream, "%*sFree Blocks (offset, size):\n", indent, ""); for (free_block=0, freelist = h->freelist; freelist; freelist = freelist->next, free_block++) { char temp_str[32]; sprintf(temp_str,"Block #%d:",free_block); HDfprintf(stream, "%*s%-*s %8Zu, %8Zu\n", indent+3, "", MAX(0,fwidth-9), temp_str, freelist->offset, freelist->size); if (freelist->offset + freelist->size > h->mem_alloc) { fprintf(stream, "***THAT FREE BLOCK IS OUT OF BOUNDS!\n"); } else { for (i=overlap=0; i<(int)(freelist->size); i++) { if (marker[freelist->offset + i]) overlap++; marker[freelist->offset + i] = 1; } if (overlap) { fprintf(stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS " "ONE!\n"); } else { amount_free += freelist->size; } } } if (h->mem_alloc) { fprintf(stream, "%*s%-*s %.2f%%\n", indent, "", fwidth, "Percent of heap used:", (100.0 * (double)(h->mem_alloc - amount_free) / (double)h->mem_alloc)); } /* * Print the data in a VMS-style octal dump. */ fprintf(stream, "%*sData follows (`__' indicates free region)...\n", indent, ""); for (i=0; i<(int)(h->disk_alloc); i+=16) { fprintf(stream, "%*s %8d: ", indent, "", i); for (j = 0; j < 16; j++) { if (i+j<(int)(h->disk_alloc)) { if (marker[i + j]) { fprintf(stream, "__ "); } else { c = h->chunk[H5HL_SIZEOF_HDR(f) + i + j]; fprintf(stream, "%02x ", c); } } else { fprintf(stream, " "); } if (7 == j) HDfputc(' ', stream); } for (j = 0; j < 16; j++) { if (i+j < (int)(h->disk_alloc)) { if (marker[i + j]) { HDfputc(' ', stream); } else { c = h->chunk[H5HL_SIZEOF_HDR(f) + i + j]; if (c > ' ' && c < '~') HDfputc(c, stream); else HDfputc('.', stream); } } } HDfputc('\n', stream); } done: if (h && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, h, FALSE) != SUCCEED) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); H5MM_xfree(marker); FUNC_LEAVE_NOAPI(ret_value); }
/*------------------------------------------------------------------------- * Function: H5B2_cache_hdr_load * * Purpose: Loads a B-tree header from the disk. * * Return: Success: Pointer to a new B-tree. * * Failure: NULL * * Programmer: Quincey Koziol * [email protected] * Feb 1 2005 * *------------------------------------------------------------------------- */ static H5B2_t * H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void UNUSED *udata) { const H5B2_class_t *type = (const H5B2_class_t *) _type; /* Type of B-tree */ unsigned depth; /* Depth of B-tree */ size_t node_size, rrec_size; /* Size info for B-tree */ uint8_t split_percent, merge_percent; /* Split & merge %s for B-tree */ H5B2_t *bt2 = NULL; /* B-tree info */ size_t size; /* Header size */ uint32_t stored_chksum; /* Stored metadata checksum value */ uint32_t computed_chksum; /* Computed metadata checksum value */ H5WB_t *wb = NULL; /* Wrapped buffer for header data */ uint8_t hdr_buf[H5B2_HDR_BUF_SIZE]; /* Buffer for header */ uint8_t *hdr; /* Pointer to header buffer */ uint8_t *p; /* Pointer into raw data buffer */ H5B2_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5B2_cache_hdr_load, NULL) /* Check arguments */ HDassert(f); HDassert(H5F_addr_defined(addr)); HDassert(type); /* Allocate space for the B-tree data structure */ if(NULL == (bt2 = H5FL_MALLOC(H5B2_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") HDmemset(&bt2->cache_info, 0, sizeof(H5AC_info_t)); /* Wrap the local buffer for serialized header info */ if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf)))) HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, NULL, "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, NULL, "can't get actual buffer") /* Read header from disk */ if(H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, hdr) < 0) HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree header") /* Get temporary pointer to serialized header */ p = hdr; /* Magic number */ if(HDmemcmp(p, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree header signature") p += H5_SIZEOF_MAGIC; /* Version */ if(*p++ != H5B2_HDR_VERSION) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree header version") /* B-tree type */ if(*p++ != (uint8_t)type->id) HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree type") /* Node size (in bytes) */ UINT32DECODE(p, node_size); /* Raw key size (in bytes) */ UINT16DECODE(p, rrec_size); /* Depth of tree */ UINT16DECODE(p, depth); /* Split & merge %s */ split_percent = *p++; merge_percent = *p++; /* Root node pointer */ H5F_addr_decode(f, (const uint8_t **)&p, &(bt2->root.addr)); UINT16DECODE(p, bt2->root.node_nrec); H5F_DECODE_LENGTH(f, p, bt2->root.all_nrec); /* Metadata checksum */ UINT32DECODE(p, stored_chksum); /* Sanity check */ HDassert((size_t)(p - hdr) == size); /* Compute checksum on entire header */ computed_chksum = H5_checksum_metadata(hdr, (size - H5B2_SIZEOF_CHKSUM), 0); /* Verify checksum */ if(stored_chksum != computed_chksum) HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "incorrect metadata checksum for v2 B-tree header") /* Initialize shared B-tree info */ if(H5B2_shared_init(f, bt2, type, depth, node_size, rrec_size, split_percent, merge_percent) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't create shared B-tree info") /* Set return value */ ret_value = bt2; done: /* Release resources */ if(wb && H5WB_unwrap(wb) < 0) HDONE_ERROR(H5E_BTREE, H5E_CLOSEERROR, NULL, "can't close wrapped buffer") if(!ret_value && bt2) (void)H5B2_cache_hdr_dest(f, bt2); FUNC_LEAVE_NOAPI(ret_value) } /* end H5B2_cache_hdr_load() */ /*lint !e818 Can't make udata a pointer to const */
/*------------------------------------------------------------------------- * Function: H5B2__create_leaf * * Purpose: Creates empty leaf node of a B-tree and update node pointer * to point to it. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * [email protected] * Feb 2 2005 * *------------------------------------------------------------------------- */ herr_t H5B2__create_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, void *parent, H5B2_node_ptr_t *node_ptr) { H5B2_leaf_t *leaf = NULL; /* Pointer to new leaf node created */ hbool_t inserted = FALSE; /* Whether the leaf node was inserted into cache */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE /* Check arguments. */ HDassert(hdr); HDassert(node_ptr); /* Allocate memory for leaf information */ if(NULL == (leaf = H5FL_CALLOC(H5B2_leaf_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree leaf info") /* Increment ref. count on B-tree header */ if(H5B2__hdr_incr(hdr) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINC, FAIL, "can't increment ref. count on B-tree header") /* Share B-tree header information */ leaf->hdr = hdr; /* Allocate space for the native keys in memory */ if(NULL == (leaf->leaf_native = (uint8_t *)H5FL_FAC_MALLOC(hdr->node_info[0].nat_rec_fac))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree leaf native keys") HDmemset(leaf->leaf_native, 0, hdr->cls->nrec_size * hdr->node_info[0].max_nrec); /* Set parent */ leaf->parent = parent; /* Set shadowed epoch to header's epoch */ leaf->shadow_epoch = hdr->shadow_epoch; /* Allocate space on disk for the leaf */ if(HADDR_UNDEF == (node_ptr->addr = H5MF_alloc(hdr->f, H5FD_MEM_BTREE, dxpl_id, (hsize_t)hdr->node_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree leaf node") /* Cache the new B-tree node */ if(H5AC_insert_entry(hdr->f, dxpl_id, H5AC_BT2_LEAF, node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't add B-tree leaf to cache") inserted = TRUE; /* Add leaf node as child of 'top' proxy */ if(hdr->top_proxy) { if(H5AC_proxy_entry_add_child(hdr->top_proxy, hdr->f, dxpl_id, leaf) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTSET, FAIL, "unable to add v2 B-tree node as child of proxy") leaf->top_proxy = hdr->top_proxy; } /* end if */ done: if(ret_value < 0) { if(leaf) { /* Remove from cache, if inserted */ if(inserted) if(H5AC_remove_entry(leaf) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTREMOVE, FAIL, "unable to remove v2 B-tree leaf node from cache") /* Release leaf node's disk space */ if(H5F_addr_defined(node_ptr->addr) && H5MF_xfree(hdr->f, H5FD_MEM_BTREE, dxpl_id, node_ptr->addr, (hsize_t)hdr->node_size) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to release file space for v2 B-tree leaf node") /* Destroy leaf node */ if(H5B2__leaf_free(leaf) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to release v2 B-tree leaf node") } /* end if */ } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* H5B2__create_leaf() */
/*------------------------------------------------------------------------- * 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: H5B2__protect_leaf * * Purpose: "Protect" an leaf node in the metadata cache * * Return: Pointer to leaf node on success/NULL on failure * * Programmer: Quincey Koziol * [email protected] * May 5 2010 * *------------------------------------------------------------------------- */ H5B2_leaf_t * H5B2__protect_leaf(H5B2_hdr_t *hdr, hid_t dxpl_id, void *parent, H5B2_node_ptr_t *node_ptr, hbool_t shadow, unsigned flags) { H5B2_leaf_cache_ud_t udata; /* User-data for callback */ H5B2_leaf_t *leaf; /* v2 B-tree leaf node */ H5B2_leaf_t *ret_value = NULL; /* Return value */ FUNC_ENTER_PACKAGE /* Check arguments. */ HDassert(hdr); HDassert(node_ptr); HDassert(H5F_addr_defined(node_ptr->addr)); /* only H5AC__READ_ONLY_FLAG may appear in flags */ HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0); /* Set up user data for callback */ udata.f = hdr->f; udata.hdr = hdr; udata.parent = parent; udata.nrec = node_ptr->node_nrec; /* Protect the leaf node */ if(NULL == (leaf = (H5B2_leaf_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_BT2_LEAF, node_ptr->addr, &udata, flags))) HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, NULL, "unable to protect B-tree leaf node") /* Create top proxy, if it doesn't exist */ if(hdr->top_proxy && NULL == leaf->top_proxy) { /* Add leaf node as child of 'top' proxy */ if(H5AC_proxy_entry_add_child(hdr->top_proxy, hdr->f, dxpl_id, leaf) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTSET, NULL, "unable to add v2 B-tree leaf node as child of proxy") leaf->top_proxy = hdr->top_proxy; } /* end if */ /* Shadow the node, if requested */ if(shadow) if(H5B2__shadow_leaf(leaf, dxpl_id, node_ptr) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, NULL, "unable to shadow leaf node") /* Set return value */ ret_value = leaf; done: /* Clean up on error */ if(!ret_value) { /* Release the leaf node, if it was protected */ if(leaf) { /* Remove from v2 B-tree's proxy, if added */ if(leaf->top_proxy) { if(H5AC_proxy_entry_remove_child(leaf->top_proxy, leaf) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTUNDEPEND, NULL, "unable to destroy flush dependency between leaf node and v2 B-tree 'top' proxy") leaf->top_proxy = NULL; } /* end if */ /* Unprotect leaf node */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, NULL, "unable to unprotect v2 B-tree leaf node, address = %llu", (unsigned long long)node_ptr->addr) } /* end if */ } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* H5B2__protect_leaf() */