diff options
Diffstat (limited to 'src/H5MF.c')
-rw-r--r-- | src/H5MF.c | 496 |
1 files changed, 325 insertions, 171 deletions
@@ -75,6 +75,10 @@ typedef enum { /* Local Prototypes */ /********************/ +/* Allocator routines */ +static herr_t H5MF_alloc_create(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type); +static herr_t H5MF_alloc_close(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type); + /*********************/ /* Package Variables */ @@ -195,11 +199,10 @@ H5MF_init_merge_flags(H5F_t *f) /*------------------------------------------------------------------------- - * Function: H5MF_alloc_start + * Function: H5MF_alloc_open * - * Purpose: "Start up" free space for file - open existing free space - * structure if one exists, otherwise create a new free space - * structure + * Purpose: Open an existing free space manager of TYPE for file by + * creating a free-space structure * * Return: Success: non-negative * Failure: negative @@ -208,19 +211,112 @@ H5MF_init_merge_flags(H5F_t *f) * koziol@hdfgroup.org * Jan 8 2008 * - * Modifications: - * Vailin Choi, July 29th, 2008 - * Pass values of alignment and threshold to FS_create() for handling alignment - * *------------------------------------------------------------------------- */ herr_t -H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, hbool_t may_create) +H5MF_alloc_open(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type) { const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for file */ H5MF_FSPACE_SECT_CLS_SIMPLE}; herr_t ret_value = SUCCEED; /* Return value */ + FUNC_ENTER_NOAPI_NOINIT(H5MF_alloc_open) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(f->shared); + HDassert(H5F_addr_defined(f->shared->fs_addr[type])); + HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED); + + /* Open an existing free space structure for the file */ + if(NULL == (f->shared->fs_man[type] = H5FS_open(f, dxpl_id, f->shared->fs_addr[type], + NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info") + + /* Set the state for the free space manager to "open", if it is now */ + if(f->shared->fs_man[type]) + f->shared->fs_state[type] = H5F_FS_STATE_OPEN; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_alloc_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_alloc_create + * + * Purpose: Create free space manager of TYPE for the file by creating + * a free-space structure + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jan 8 2008 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5MF_alloc_create(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type) +{ + const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for file */ + H5MF_FSPACE_SECT_CLS_SIMPLE}; + herr_t ret_value = SUCCEED; /* Return value */ + H5FS_create_t fs_create; /* Free space creation parameters */ + + FUNC_ENTER_NOAPI_NOINIT(H5MF_alloc_create) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(f->shared); + HDassert(!H5F_addr_defined(f->shared->fs_addr[type])); + HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED); + + /* Set the free space creation parameters */ + fs_create.client = H5FS_CLIENT_FILE_ID; + fs_create.shrink_percent = H5MF_FSPACE_SHRINK; + fs_create.expand_percent = H5MF_FSPACE_EXPAND; + fs_create.max_sect_addr = 1 + H5V_log2_gen((uint64_t)f->shared->maxaddr); + fs_create.max_sect_size = f->shared->maxaddr; + + if(NULL == (f->shared->fs_man[type] = H5FS_create(f, dxpl_id, NULL, + &fs_create, NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info") + + + /* Set the state for the free space manager to "open", if it is now */ + if(f->shared->fs_man[type]) + f->shared->fs_state[type] = H5F_FS_STATE_OPEN; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_alloc_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_alloc_start + * + * Purpose: Open or create a free space manager of a given type + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Jan 8 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type) +{ + herr_t ret_value = SUCCEED; /* Return value */ + FUNC_ENTER_NOAPI_NOINIT(H5MF_alloc_start) /* @@ -229,50 +325,62 @@ H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, hbool_t may_create) HDassert(f); HDassert(f->shared); - /* Check for creating free space info for the file */ + /* Check if the free space manager exists already */ if(H5F_addr_defined(f->shared->fs_addr[type])) { - /* Open an existing free space structure for the file */ - HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED); - if(NULL == (f->shared->fs_man[type] = H5FS_open(f, dxpl_id, f->shared->fs_addr[type], - NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info") + /* Open existing free space manager */ + if(H5MF_alloc_open(f, dxpl_id, type) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTOPENOBJ, FAIL, "can't initialize file free space") } /* end if */ else { - /* Check if we are allowed to create the free space manager */ - if(may_create) { - H5FS_create_t fs_create; /* Free space creation parameters */ - - /* Set the free space creation parameters */ - fs_create.client = H5FS_CLIENT_FILE_ID; - fs_create.shrink_percent = H5MF_FSPACE_SHRINK; - fs_create.expand_percent = H5MF_FSPACE_EXPAND; - fs_create.max_sect_addr = 1 + H5V_log2_gen((uint64_t)f->shared->maxaddr); - fs_create.max_sect_size = f->shared->maxaddr; - - /* Create the free space structure for the heap */ - HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED); -#ifdef LATER - if(NULL == (f->shared->fs_man[type] = H5FS_create(f, dxpl_id, &f->shared->fs_addr[type], - &fs_create, NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info") -#else /* LATER */ - if(NULL == (f->shared->fs_man[type] = H5FS_create(f, dxpl_id, NULL, - &fs_create, NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info") -#endif /* LATER */ - } /* end if */ + /* Create new free space manager */ + if(H5MF_alloc_create(f, dxpl_id, type) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCREATE, FAIL, "can't initialize file free space") } /* end else */ - /* Set the state for the free space manager to "open", if it is now */ - if(f->shared->fs_man[type]) - f->shared->fs_state[type] = H5F_FS_STATE_OPEN; - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5MF_alloc_start() */ /*------------------------------------------------------------------------- + * Function: H5MF_alloc_close + * + * Purpose: Close an existing free space manager of TYPE for file + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Vailin Choi; July 1st, 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5MF_alloc_close(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5MF_alloc_close) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(f->shared); + HDassert(f->shared->fs_man[type]); + HDassert(f->shared->fs_state[type] != H5F_FS_STATE_CLOSED); + + /* Close an existing free space structure for the file */ + if(H5FS_close(f, dxpl_id, f->shared->fs_man[type]) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release free space info") + f->shared->fs_man[type] = NULL; + f->shared->fs_state[type] = H5F_FS_STATE_CLOSED; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_alloc_close() */ + + +/*------------------------------------------------------------------------- * Function: H5MF_alloc * * Purpose: Allocate SIZE bytes of file memory and return the relative @@ -309,83 +417,75 @@ HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", FUNC, (unsigned)alloc_typ /* Get free space type from allocation type */ fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type); - /* Check if the free space manager for the file has been initialized */ - if(!f->shared->fs_man[fs_type]) - if(H5MF_alloc_start(f, dxpl_id, fs_type, FALSE) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "can't initialize file free space") - - /* Search for large enough space in the free space manager */ - if(f->shared->fs_man[fs_type]) { - H5MF_free_section_t *node; /* Free space section pointer */ - htri_t node_found = FALSE; /* Whether an existing free list node was found */ - - /* Try to get a section from the free space manager */ - if((node_found = H5FS_sect_find(f, dxpl_id, f->shared->fs_man[fs_type], size, (H5FS_section_info_t **)&node)) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "error locating free space in file") + /* Check if we are using the free space manager for this file */ + if(H5F_HAVE_FREE_SPACE_MANAGER(f)) { + /* Check if the free space manager for the file has been initialized */ + if(!f->shared->fs_man[fs_type] && H5F_addr_defined(f->shared->fs_addr[fs_type])) + if(H5MF_alloc_open(f, dxpl_id, fs_type) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTOPENOBJ, HADDR_UNDEF, "can't initialize file free space") + + /* Search for large enough space in the free space manager */ + if(f->shared->fs_man[fs_type]) { + H5MF_free_section_t *node; /* Free space section pointer */ + htri_t node_found = FALSE; /* Whether an existing free list node was found */ + + /* Try to get a section from the free space manager */ + if((node_found = H5FS_sect_find(f, dxpl_id, f->shared->fs_man[fs_type], size, (H5FS_section_info_t **)&node)) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "error locating free space in file") #ifdef H5MF_ALLOC_DEBUG_MORE HDfprintf(stderr, "%s: Check 1.5, node_found = %t\n", FUNC, node_found); #endif /* H5MF_ALLOC_DEBUG_MORE */ - /* Check for actually finding section */ - if(node_found) { - /* Sanity check */ - HDassert(node); + /* Check for actually finding section */ + if(node_found) { + /* Sanity check */ + HDassert(node); - /* Retrieve return value */ - ret_value = node->sect_info.addr; + /* Retrieve return value */ + ret_value = node->sect_info.addr; - /* Check for eliminating the section */ - if(node->sect_info.size == size) { + /* Check for eliminating the section */ + if(node->sect_info.size == size) { #ifdef H5MF_ALLOC_DEBUG_MORE HDfprintf(stderr, "%s: Check 1.6, freeing node\n", FUNC); #endif /* H5MF_ALLOC_DEBUG_MORE */ - /* Free section node */ - if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, HADDR_UNDEF, "can't free simple section node") - } /* end if */ - else { - H5MF_sect_ud_t udata; /* User data for callback */ + /* Free section node */ + if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, HADDR_UNDEF, "can't free simple section node") + } /* end if */ + else { + H5MF_sect_ud_t udata; /* User data for callback */ - /* Adjust information for section */ - node->sect_info.addr += size; - node->sect_info.size -= size; + /* Adjust information for section */ + node->sect_info.addr += size; + node->sect_info.size -= size; - /* Construct user data for callbacks */ - udata.f = f; - udata.dxpl_id = dxpl_id; - udata.alloc_type = alloc_type; - udata.allow_sect_absorb = TRUE; + /* Construct user data for callbacks */ + udata.f = f; + udata.dxpl_id = dxpl_id; + udata.alloc_type = alloc_type; + udata.allow_sect_absorb = TRUE; #ifdef H5MF_ALLOC_DEBUG_MORE HDfprintf(stderr, "%s: Check 1.7, re-adding node, node->sect_info.size = %Hu\n", FUNC, node->sect_info.size); #endif /* H5MF_ALLOC_DEBUG_MORE */ - /* Re-insert section node into file's free space */ - if(H5FS_sect_add(f, dxpl_id, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, HADDR_UNDEF, "can't re-add section to file free space") - } /* end else */ + /* Re-insert section node into file's free space */ + if(H5FS_sect_add(f, dxpl_id, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, HADDR_UNDEF, "can't re-add section to file free space") + } /* end else */ - /* Leave now */ - HGOTO_DONE(ret_value) + /* Leave now */ + HGOTO_DONE(ret_value) + } /* end if */ } /* end if */ - } /* end if */ #ifdef H5MF_ALLOC_DEBUG_MORE HDfprintf(stderr, "%s: Check 2.0\n", FUNC); #endif /* H5MF_ALLOC_DEBUG_MORE */ - - /* Couldn't find anything from the free space manager, go allocate some */ - if(alloc_type != H5FD_MEM_DRAW) { - /* Handle metadata differently from "raw" data */ - if(HADDR_UNDEF == (ret_value = H5MF_aggr_alloc(f, dxpl_id, &(f->shared->meta_aggr), &(f->shared->sdata_aggr), alloc_type, size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata") } /* end if */ - else { - /* Allocate "raw" data */ - if(HADDR_UNDEF == (ret_value = H5MF_aggr_alloc(f, dxpl_id, &(f->shared->sdata_aggr), &(f->shared->meta_aggr), alloc_type, size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data") - } /* end else */ - /* Sanity check for overlapping into file's temporary allocation space */ - HDassert(H5F_addr_le((ret_value + size), f->shared->tmp_addr)); + /* Allocate from the metadata aggregator (or the VFD) */ + if(HADDR_UNDEF == (ret_value = H5MF_aggr_vfd_alloc(f, alloc_type, dxpl_id, size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "allocation failed from aggr/vfd") done: #ifdef H5MF_ALLOC_DEBUG @@ -394,6 +494,7 @@ HDfprintf(stderr, "%s: Leaving: ret_value = %a, size = %Hu\n", FUNC, ret_value, #ifdef H5MF_ALLOC_DEBUG_DUMP H5MF_sects_dump(f, dxpl_id, stderr); #endif /* H5MF_ALLOC_DEBUG_DUMP */ + FUNC_LEAVE_NOAPI(ret_value) } /* end H5MF_alloc() */ @@ -531,23 +632,26 @@ HDfprintf(stderr, "%s: Trying to avoid starting up free space manager\n", FUNC); /* If we are deleting the free space manager, leave now, to avoid * [re-]starting it. + * or if file space strategy type is not using a free space manager + * (H5F_FILE_SPACE_AGGR_VFD or H5F_FILE_SPACE_VFD), drop free space + * section on the floor. * * Note: this drops the space to free on the floor... * */ - if(f->shared->fs_state[fs_type] == H5F_FS_STATE_DELETING) -{ + if(f->shared->fs_state[fs_type] == H5F_FS_STATE_DELETING || + !H5F_HAVE_FREE_SPACE_MANAGER(f)) { #ifdef H5MF_ALLOC_DEBUG_MORE HDfprintf(stderr, "%s: dropping addr = %a, size = %Hu, on the floor!\n", FUNC, addr, size); #endif /* H5MF_ALLOC_DEBUG_MORE */ HGOTO_DONE(SUCCEED) -} + } /* end if */ /* There's either already a free space manager, or the freed * space isn't at the end of the file, so start up (or create) * the file space manager */ - if(H5MF_alloc_start(f, dxpl_id, fs_type, TRUE) < 0) + if(H5MF_alloc_start(f, dxpl_id, fs_type) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space") } /* end if */ HDassert(f->shared->fs_man[fs_type]); @@ -568,14 +672,14 @@ HDfprintf(stderr, "%s: Before H5FS_sect_add()\n", FUNC); #endif /* H5MF_ALLOC_DEBUG_MORE */ if(H5FS_sect_add(f, dxpl_id, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't add section to file free space") + node = NULL; #ifdef H5MF_ALLOC_DEBUG_MORE HDfprintf(stderr, "%s: After H5FS_sect_add()\n", FUNC); #endif /* H5MF_ALLOC_DEBUG_MORE */ - node = NULL; done: - if(ret_value < 0 && node) - /* On error, free section node allocated */ + /* Release section node, if allocated and not added to section list or merged */ + if(node) if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0) HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node") @@ -635,8 +739,8 @@ HDfprintf(stderr, "%s: Entering: alloc_type = %u, addr = %a, size = %Hu, extra_r fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type); /* Check if the free space for the file has been initialized */ - if(!f->shared->fs_man[fs_type]) - if(H5MF_alloc_start(f, dxpl_id, fs_type, FALSE) < 0) + if(!f->shared->fs_man[fs_type] && H5F_addr_defined(f->shared->fs_addr[fs_type])) + if(H5MF_alloc_open(f, dxpl_id, fs_type) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space") /* Check for test block able to block in free space manager */ @@ -670,8 +774,8 @@ H5MF_sects_dump(f, dxpl_id, stderr); * *------------------------------------------------------------------------- */ -hssize_t -H5MF_get_freespace(H5F_t *f, hid_t dxpl_id) +herr_t +H5MF_get_freespace(H5F_t *f, hid_t dxpl_id, hsize_t *tot_space, hsize_t *meta_size) { haddr_t eoa; /* End of allocated space in the file */ haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */ @@ -679,8 +783,9 @@ H5MF_get_freespace(H5F_t *f, hid_t dxpl_id) haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */ hsize_t sda_size = 0; /* Size of "small data aggregator" */ hsize_t tot_fs_size = 0; /* Amount of all free space managed */ + hsize_t tot_meta_size = 0; /* Amount of metadata for free space managers */ H5FD_mem_t type; /* Memory type for iteration */ - hssize_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5MF_get_freespace, FAIL) @@ -694,38 +799,53 @@ H5MF_get_freespace(H5F_t *f, hid_t dxpl_id) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed") /* Retrieve metadata aggregator info, if available */ - H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if(H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query metadata aggregator stats") /* Retrieve 'small data' aggregator info, if available */ - H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size); + if(H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query small data aggregator stats") /* Iterate over all the free space types that have managers and get each free list's space */ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) { - hsize_t type_fs_size = 0; /* Amount of free space managed for each type */ + hbool_t fs_started = FALSE; - /* Check if the free space for the file has been initialized */ - if(!f->shared->fs_man[type]) - if(H5MF_alloc_start(f, dxpl_id, type, FALSE) < 0) + /* Check if the free space for the file has been initialized */ + if(!f->shared->fs_man[type] && H5F_addr_defined(f->shared->fs_addr[type])) { + if(H5MF_alloc_open(f, dxpl_id, type) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space") + HDassert(f->shared->fs_man[type]); + fs_started = TRUE; + } /* end if */ - /* Retrieve free space size from free space manager */ - if(f->shared->fs_man[type]) - if((ret_value = H5FS_sect_stats(f->shared->fs_man[type], &type_fs_size, NULL)) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query free space stats") + /* Check if there's free space of this type */ + if(f->shared->fs_man[type]) { + hsize_t type_fs_size = 0; /* Amount of free space managed for each type */ + hsize_t type_meta_size = 0; /* Amount of free space metadata for each type */ - /* Increment total free space for types */ - tot_fs_size += type_fs_size; + /* Retrieve free space size from free space manager */ + if(H5FS_sect_stats(f->shared->fs_man[type], &type_fs_size, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query free space stats") + if(H5FS_size(f, f->shared->fs_man[type], &type_meta_size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query free space metadata stats") + + /* Increment total free space for types */ + tot_fs_size += type_fs_size; + tot_meta_size += type_meta_size; + } /* end if */ + + /* Close the free space manager, if we opened it here */ + if(fs_started) + if(H5MF_alloc_close(f, dxpl_id, type) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't close file free space") } /* end for */ - /* Start computing value to return */ - ret_value = tot_fs_size; - /* Check for aggregating metadata allocations */ if(ma_size > 0) { /* Add in the reserved space for metadata to the available free space */ /* (if it's not at the tail of the file) */ if(H5F_addr_ne(ma_addr + ma_size, eoa)) - ret_value += ma_size; + tot_fs_size += ma_size; } /* end if */ /* Check for aggregating small data allocations */ @@ -733,9 +853,15 @@ H5MF_get_freespace(H5F_t *f, hid_t dxpl_id) /* Add in the reserved space for metadata to the available free space */ /* (if it's not at the tail of the file) */ if(H5F_addr_ne(sda_addr + sda_size, eoa)) - ret_value += sda_size; + tot_fs_size += sda_size; } /* end if */ + /* Set the value(s) to return */ + if(tot_space) + *tot_space = tot_fs_size; + if(meta_size) + *meta_size = tot_meta_size; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5MF_get_freespace() */ @@ -807,6 +933,74 @@ HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value); /*------------------------------------------------------------------------- + * Function: H5MF_free_aggrs + * + * Purpose: Reset a block aggregator, returning any space back to file + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Vailin Choi + * July 1st, 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5MF_free_aggrs(H5F_t *f, hid_t dxpl_id) +{ + H5F_blk_aggr_t *first_aggr; /* First aggregator to reset */ + H5F_blk_aggr_t *second_aggr; /* Second aggregator to reset */ + haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */ + hsize_t ma_size = 0; /* Size of "metadata aggregator" */ + haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */ + hsize_t sda_size = 0; /* Size of "small data aggregator" */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5MF_free_aggrs, FAIL) + + /* Check args */ + HDassert(f); + HDassert(f->shared); + HDassert(f->shared->lf); + + /* Retrieve metadata aggregator info, if available */ + if(H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query metadata aggregator stats") + + /* Retrieve 'small data' aggregator info, if available */ + if(H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query small data aggregator stats") + + /* Make certain we release the aggregator that's later in the file first */ + /* (so the file shrinks properly) */ + if(H5F_addr_defined(ma_addr) && H5F_addr_defined(sda_addr)) { + if(H5F_addr_lt(ma_addr, sda_addr)) { + first_aggr = &(f->shared->sdata_aggr); + second_aggr = &(f->shared->meta_aggr); + } /* end if */ + else { + first_aggr = &(f->shared->meta_aggr); + second_aggr = &(f->shared->sdata_aggr); + } /* end else */ + } /* end if */ + else { + first_aggr = &(f->shared->meta_aggr); + second_aggr = &(f->shared->sdata_aggr); + } /* end else */ + + /* Release the unused portion of the metadata and "small data" blocks back + * to the free lists in the file. + */ + if(H5MF_aggr_reset(f, dxpl_id, first_aggr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't reset metadata block") + if(H5MF_aggr_reset(f, dxpl_id, second_aggr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't reset 'small data' block") +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5MF_free_aggrs() */ + + +/*------------------------------------------------------------------------- * Function: H5MF_close * * Purpose: Close the free space tracker(s) for a file @@ -822,12 +1016,6 @@ herr_t H5MF_close(H5F_t *f, hid_t dxpl_id) { H5FD_mem_t type; /* Memory type for iteration */ - H5F_blk_aggr_t *first_aggr; /* First aggregator to reset */ - H5F_blk_aggr_t *second_aggr; /* Second aggregator to reset */ - haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */ - hsize_t ma_size = 0; /* Size of "metadata aggregator" */ - haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */ - hsize_t sda_size = 0; /* Size of "small data aggregator" */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5MF_close, FAIL) @@ -851,7 +1039,7 @@ HDfprintf(stderr, "%s: Check 1.0 - f->shared->fs_man[%u] = %p, f->shared->fs_add HDfprintf(stderr, "%s: Before closing free space manager\n", FUNC); #endif /* H5MF_ALLOC_DEBUG_MORE */ if(H5FS_close(f, dxpl_id, f->shared->fs_man[type]) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info") + HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release free space info") f->shared->fs_man[type] = NULL; f->shared->fs_state[type] = H5F_FS_STATE_CLOSED; } /* end if */ @@ -878,8 +1066,8 @@ HDfprintf(stderr, "%s: Check 2.0 - f->shared->fs_man[%u] = %p, f->shared->fs_add HDfprintf(stderr, "%s: Before deleting free space manager\n", FUNC); #endif /* H5MF_ALLOC_DEBUG_MORE */ /* Delete free space manager for this type */ - if(H5FS_delete(f, dxpl_id, tmp_fs_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't delete free space manager") + if(H5FS_delete(f, dxpl_id, tmp_fs_addr) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't delete free space manager") /* Shift [back] to closed state */ HDassert(f->shared->fs_state[type] == H5F_FS_STATE_DELETING); @@ -890,42 +1078,8 @@ HDfprintf(stderr, "%s: Before deleting free space manager\n", FUNC); } /* end if */ } /* end for */ - /* Retrieve metadata aggregator info, if available */ - H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); -#ifdef H5MF_ALLOC_DEBUG_MORE -HDfprintf(stderr, "%s: ma_addr = %a, ma_size = %Hu, end of ma = %a\n", FUNC, ma_addr, ma_size, (haddr_t)((ma_addr + ma_size) - 1)); -#endif /* H5MF_ALLOC_DEBUG_MORE */ - - /* Retrieve 'small data' aggregator info, if available */ - H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size); -#ifdef H5MF_ALLOC_DEBUG_MORE -HDfprintf(stderr, "%s: sda_addr = %a, sda_size = %Hu, end of sda = %a\n", FUNC, sda_addr, sda_size, (haddr_t)((sda_addr + sda_size) - 1)); -#endif /* H5MF_ALLOC_DEBUG_MORE */ - - /* Make certain we release the aggregator that's later in the file first */ - /* (so the file shrinks properly) */ - if(H5F_addr_defined(ma_addr) && H5F_addr_defined(sda_addr)) { - if(H5F_addr_lt(ma_addr, sda_addr)) { - first_aggr = &(f->shared->sdata_aggr); - second_aggr = &(f->shared->meta_aggr); - } /* end if */ - else { - first_aggr = &(f->shared->meta_aggr); - second_aggr = &(f->shared->sdata_aggr); - } /* end else */ - } /* end if */ - else { - first_aggr = &(f->shared->meta_aggr); - second_aggr = &(f->shared->sdata_aggr); - } /* end else */ - - /* Release the unused portion of the metadata and "small data" blocks back - * to the free lists in the file. - */ - if(H5MF_aggr_reset(f, dxpl_id, first_aggr) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't reset metadata block") - if(H5MF_aggr_reset(f, dxpl_id, second_aggr) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't reset 'small data' block") + if(H5MF_free_aggrs(f, dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't free aggregators") done: #ifdef H5MF_ALLOC_DEBUG |