/*------------------------------------------------------------------------- * Function: H5MF_aggr_alloc * * Purpose: Try to allocate SIZE bytes of memory from an aggregator * block if possible. * * Return: Success: The format address of the new file memory. * Failure: The undefined address HADDR_UNDEF * * Programmer: Quincey Koziol * Thursday, December 13, 2007 * *------------------------------------------------------------------------- */ haddr_t H5MF_aggr_alloc(H5F_t *f, hid_t dxpl_id, H5F_blk_aggr_t *aggr, H5F_blk_aggr_t *other_aggr, H5FD_mem_t type, hsize_t size) { haddr_t eoa_frag_addr = HADDR_UNDEF; /* Address of fragment at EOA */ hsize_t eoa_frag_size = 0; /* Size of fragment at EOA */ haddr_t eoa = HADDR_UNDEF; /* Initial EOA for the file */ haddr_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(HADDR_UNDEF) #ifdef H5MF_AGGR_DEBUG HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); #endif /* H5MF_AGGR_DEBUG */ /* check args */ HDassert(f); HDassert(aggr); HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); HDassert(other_aggr); HDassert(other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); HDassert(other_aggr->feature_flag != aggr->feature_flag); HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); HDassert(size > 0); /* Get the EOA for the file */ if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, type))) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, HADDR_UNDEF, "Unable to get eoa") /* * If the aggregation feature is enabled for this file and strategy is not H5F_FILE_SPACE_VFD, * allocate "generic" space and sub-allocate out of that, if possible. * Otherwise just allocate through H5FD_alloc(). */ if((f->shared->feature_flags & aggr->feature_flag) && f->shared->fs_strategy != H5F_FILE_SPACE_VFD) { haddr_t aggr_frag_addr = HADDR_UNDEF; /* Address of aggregrator fragment */ hsize_t aggr_frag_size = 0; /* Size of aggregator fragment */ hsize_t alignment; /* Alignment of this section */ hsize_t aggr_mis_align = 0; /* Mis-alignment of aggregator */ H5FD_mem_t alloc_type, other_alloc_type;/* Current aggregator & 'other' aggregator types */ #ifdef H5MF_AGGR_DEBUG HDfprintf(stderr, "%s: aggr = {%a, %Hu, %Hu}\n", FUNC, aggr->addr, aggr->tot_size, aggr->size); #endif /* H5MF_AGGR_DEBUG */ /* Turn off alignment if allocation < threshold */ alignment = f->shared->alignment; if(!((alignment > 1) && (size >= f->shared->threshold))) alignment = 0; /* no alignment */ /* Generate fragment if aggregator is mis-aligned */ if(alignment && aggr->addr > 0 && aggr->size > 0 && (aggr_mis_align = (aggr->addr + H5FD_get_base_addr(f->shared->lf)) % alignment)) { aggr_frag_addr = aggr->addr; aggr_frag_size = alignment - aggr_mis_align; } /* end if */ alloc_type = aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW; other_alloc_type = other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW; /* Check if the space requested is larger than the space left in the block */ if((size + aggr_frag_size) > aggr->size) { htri_t was_extended = FALSE; /* Whether the file was extended */ /* Check if the block asked for is too large for 'normal' aggregator block */ if(size >= aggr->alloc_size) { hsize_t ext_size = size + aggr_frag_size; /* Check for overlapping into file's temporary allocation space */ if(H5F_addr_gt((aggr->addr + aggr->size + ext_size), f->shared->tmp_addr)) HGOTO_ERROR(H5E_RESOURCE, H5E_BADRANGE, HADDR_UNDEF, "'normal' file space allocation request will overlap into 'temporary' file space") if ((aggr->addr > 0) && (was_extended = H5FD_try_extend(f->shared->lf, alloc_type, f, aggr->addr + aggr->size, ext_size)) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't extending space") else if (was_extended) { /* aggr->size is unchanged */ ret_value = aggr->addr + aggr_frag_size; aggr->addr += ext_size; aggr->tot_size += ext_size; } else { /* Check for overlapping into file's temporary allocation space */ if(H5F_addr_gt((eoa + size), f->shared->tmp_addr)) HGOTO_ERROR(H5E_RESOURCE, H5E_BADRANGE, HADDR_UNDEF, "'normal' file space allocation request will overlap into 'temporary' file space") /* Release "other" aggregator, if it exists, is at the end of the allocated space, * has allocated more than one block and the unallocated space is greater than its * allocation block size. */ if ((other_aggr->size > 0) && (H5F_addr_eq((other_aggr->addr + other_aggr->size), eoa)) && (other_aggr->tot_size > other_aggr->size) && ((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size)) { if(H5MF_aggr_free(f, dxpl_id, other_alloc_type, other_aggr) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") } /* end if */ /* Allocate space from the VFD (i.e. at the end of the file) */ if(HADDR_UNDEF == (ret_value = H5FD_alloc(f->shared->lf, dxpl_id, alloc_type, f, size, &eoa_frag_addr, &eoa_frag_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block") } /* end else */ } /* end if */
/*------------------------------------------------------------------------- * Function: test_1 * * Purpose: Writes a sequence of objects to the global heap where each * object is larger than the one before. * * Return: Success: 0 * * Failure: number of errors * * Programmer: Robb Matzke * Tuesday, March 31, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static int test_1 (hid_t fapl) { hid_t file = -1; H5F_t *f = NULL; H5HG_t obj[1024]; uint8_t out[1024]; uint8_t in[1024]; int i; size_t size; herr_t status; int nerrors = 0; char filename[1024]; TESTING("monotonically increasing lengths"); /* Open a clean file */ h5_fixname(FILENAME[0], fapl, filename, sizeof filename); if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) goto error; if(NULL == (f = (H5F_t *)H5I_object(file))) { H5_FAILED(); puts(" Unable to create file"); goto error; } /* * Write the objects, monotonically increasing in length. Since this is * a clean file, the addresses allocated for the collections should also * be monotonically increasing. */ for(i = 0; i < 1024; i++) { size = i + 1; HDmemset(out, 'A' + i % 26, size); H5Eclear2(H5E_DEFAULT); status = H5HG_insert(f, H5P_DATASET_XFER_DEFAULT, size, out, obj + i); if(status < 0) { H5_FAILED(); puts(" Unable to insert object into global heap"); nerrors++; } else if(i && H5F_addr_gt(obj[i - 1].addr, obj[i].addr)) { H5_FAILED(); puts(" Collection addresses are not monotonically increasing"); nerrors++; } } /* * Now try to read each object back. */ for(i = 0; i < 1024; i++) { size = i + 1; HDmemset(out, 'A' + i % 26, size); H5Eclear2(H5E_DEFAULT); if(NULL == H5HG_read(f, H5P_DATASET_XFER_DEFAULT, obj + i, in, NULL)) { H5_FAILED(); puts(" Unable to read object"); nerrors++; } else if(HDmemcmp(in, out, size)) { H5_FAILED(); puts(" Value read doesn't match value written"); nerrors++; } } if(H5Fclose(file) < 0) goto error; if(nerrors) goto error; PASSED(); return 0; error: H5E_BEGIN_TRY { H5Fclose(file); } H5E_END_TRY; return MAX(1, nerrors); }