/*------------------------------------------------------------------------- * Function: H5FS_close * * Purpose: Destroy & deallocate free list structure, serializing sections * in the bins * * Return: Success: non-negative * * Failure: negative * * Programmer: Quincey Koziol * Tuesday, March 7, 2006 * *------------------------------------------------------------------------- */ herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_TAG(dxpl_id, H5AC__FREESPACE_TAG, FAIL) /* Check arguments. */ HDassert(f); HDassert(fspace); #ifdef H5FS_DEBUG HDfprintf(stderr, "%s: Entering, fspace = %p, fspace->addr = %a, fspace->sinfo = %p\n", FUNC, fspace, fspace->addr, fspace->sinfo); #endif /* H5FS_DEBUG */ /* Check if section info is valid */ /* (i.e. the header "owns" the section info and it's not in the cache) */ if(fspace->sinfo) { #ifdef H5FS_DEBUG HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu, fspace->serial_sect_count = %Hu, fspace->sect_addr = %a, fspace->rc = %u\n", FUNC, fspace->tot_sect_count, fspace->serial_sect_count, fspace->sect_addr, fspace->rc); HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size); #endif /* H5FS_DEBUG */ /* If there are sections to serialize, update them */ /* (if the free space manager is persistant) */ if(fspace->serial_sect_count > 0 && H5F_addr_defined(fspace->addr)) { #ifdef H5FS_DEBUG HDfprintf(stderr, "%s: Real sections to store in file\n", FUNC); #endif /* H5FS_DEBUG */ if(fspace->sinfo->dirty) { /* Check if the section info is "floating" */ if(!H5F_addr_defined(fspace->sect_addr)) { /* Sanity check */ HDassert(fspace->sect_size > 0); /* Allocate space for the section info in file */ if(H5F_USE_TMP_SPACE(f)) { if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc_tmp(f, fspace->sect_size))) HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") } /* end if */ else { if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size))) HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") } /* end if */ fspace->alloc_sect_size = (size_t)fspace->sect_size; /* Mark free space header as dirty */ if(H5AC_mark_entry_dirty(fspace) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty") } /* end if */
/*------------------------------------------------------------------------- * Function: H5HL_dblk_realloc * * Purpose: Reallocate data block for heap * * Return: Success: Non-negative * Failure: Negative * * Programmer: Quincey Koziol * [email protected] * Oct 12 2008 * *------------------------------------------------------------------------- */ static herr_t H5HL_dblk_realloc(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t new_heap_size) { H5HL_dblk_t *dblk; /* Local heap data block */ haddr_t old_addr; /* Old location of heap data block */ haddr_t new_addr; /* New location of heap data block */ size_t old_heap_size; /* Old size of heap data block */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* check arguments */ HDassert(heap); HDassert(new_heap_size > 0); /* Release old space on disk */ old_addr = heap->dblk_addr; old_heap_size = heap->dblk_size; H5_CHECK_OVERFLOW(old_heap_size, size_t, hsize_t); if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)old_heap_size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't release old heap data?") /* Allocate new space on disk */ H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t); if(HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_size))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate file space for heap") /* Update heap info*/ heap->dblk_addr = new_addr; heap->dblk_size = new_heap_size; /* Check if heap data block actually moved in the file */ if(H5F_addr_eq(old_addr, new_addr)) { /* Check if heap data block is contiguous w/prefix */ if(heap->single_cache_obj) { /* Sanity check */ HDassert(H5F_addr_eq(heap->prfx_addr + heap->prfx_size, old_addr)); HDassert(heap->prfx); /* Resize the heap prefix in the cache */ if(H5AC_resize_entry(heap->prfx, (size_t)(heap->prfx_size + new_heap_size)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap in cache") } /* end if */ else {
/*------------------------------------------------------------------------- * 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_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: H5HF_man_dblock_create * * Purpose: Allocate & initialize a managed direct block * * Return: Pointer to new direct block on success, NULL on failure * * Programmer: Quincey Koziol * [email protected] * Feb 27 2006 * *------------------------------------------------------------------------- */ herr_t H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblock, unsigned par_entry, haddr_t *addr_p, H5HF_free_section_t **ret_sec_node) { H5HF_free_section_t *sec_node; /* Pointer to free space section for block */ H5HF_direct_t *dblock = NULL; /* Pointer to direct block */ haddr_t dblock_addr; /* Direct block's address */ size_t free_space; /* Free space in new block */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_create) /* * Check arguments. */ HDassert(hdr); /* * Allocate file and memory data structures. */ if(NULL == (dblock = H5FL_MALLOC(H5HF_direct_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap direct block") /* Reset the metadata cache info for the heap header */ HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t)); /* Share common heap information */ dblock->hdr = hdr; if(H5HF_hdr_incr(hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header") /* Set info for direct block */ if(par_iblock) { unsigned par_row = par_entry / hdr->man_dtable.cparam.width; /* Row for block */ /* Compute offset & size, based on parent's information */ dblock->block_off = par_iblock->block_off; dblock->block_off += hdr->man_dtable.row_block_off[par_row]; dblock->block_off += hdr->man_dtable.row_block_size[par_row] * (par_entry % hdr->man_dtable.cparam.width); H5_ASSIGN_OVERFLOW(/* To: */ dblock->size, /* From: */ hdr->man_dtable.row_block_size[par_row], /* From: */ hsize_t, /* To: */ size_t); } /* end if */ else { /* Must be the root direct block */ dblock->block_off = 0; dblock->size = hdr->man_dtable.cparam.start_block_size; } /* end else */ dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size); free_space = dblock->size - H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); /* Allocate buffer for block */ /* XXX: Change to using free-list factories */ if((dblock->blk = H5FL_BLK_MALLOC(direct_block, dblock->size)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") #ifdef H5_CLEAR_MEMORY HDmemset(dblock->blk, 0, dblock->size); #endif /* H5_CLEAR_MEMORY */ /* Allocate space for the direct block on disk */ if(HADDR_UNDEF == (dblock_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)dblock->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block") #ifdef QAK HDfprintf(stderr, "%s: direct block address = %a\n", FUNC, dblock_addr); #endif /* QAK */ /* Attach to parent indirect block, if there is one */ dblock->parent = par_iblock; if(dblock->parent) if(H5HF_man_iblock_attach(dblock->parent, par_entry, dblock_addr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach direct block to parent indirect block") dblock->par_entry = par_entry; /* Create a new 'single' section for the free space in the block */ if(NULL == (sec_node = H5HF_sect_single_new((dblock->block_off + H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)), free_space, dblock->parent, dblock->par_entry))) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create section for new direct block's free space") /* Check what to do with section node */ if(ret_sec_node) /* Pass back the pointer to the section instead of adding it to the free list */ *ret_sec_node = sec_node; else { /* Add new free space to the heap's list of space */ if(H5HF_space_add(hdr, dxpl_id, sec_node, 0) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") } /* end else */ /* Cache the new fractal heap direct block */ if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap direct block to cache") /* Increase the allocated heap size */ if(H5HF_hdr_inc_alloc(hdr, dblock->size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size") /* Set the address of of direct block, if requested */ if(addr_p) *addr_p = dblock_addr; done: if(ret_value < 0) if(dblock) (void)H5HF_cache_dblock_dest(hdr->f, dblock); FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_man_dblock_create() */
/*------------------------------------------------------------------------- * 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() */