diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2007-12-20 20:36:08 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2007-12-20 20:36:08 (GMT) |
commit | 6878261a432d9cc8c705aa6c4f85450b29b37150 (patch) | |
tree | 765a4e072ef63bdda33320ca2c16938c5fa7a06f /src | |
parent | 79a96581a64a4b2f8a6679100a7f369bb963ab94 (diff) | |
download | hdf5-6878261a432d9cc8c705aa6c4f85450b29b37150.zip hdf5-6878261a432d9cc8c705aa6c4f85450b29b37150.tar.gz hdf5-6878261a432d9cc8c705aa6c4f85450b29b37150.tar.bz2 |
[svn-r14353] Description:
- Add hash value for skip list string types, to reduce # of string
comparisons.
- Fixed bug with metadata/small data block aggregator adding size == 0
block into file free space list.
- Refactored metadata/small data block aggregator code into single set of
common routines.
- Changed block aggregator code to be smarter about releasing space in the
'other' block when the 'other' block has aggregated enough data.
Tested on:
FreeBSD/32 6.2 (duty) in debug mode
FreeBSD/64 6.2 (liberty) w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe,
in debug mode
Linux/64-amd64 2.6 (smirom) w/default API=1.6.x, w/C++ & FORTRAN,
in production mode
Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
in production mode
Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN,
w/szip filter, in production mode
Mac OS X/32 10.4.10 (amazon) in debug mode
Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode
Diffstat (limited to 'src')
-rw-r--r-- | src/H5F.c | 44 | ||||
-rw-r--r-- | src/H5FD.c | 759 | ||||
-rw-r--r-- | src/H5FDlog.c | 4 | ||||
-rw-r--r-- | src/H5FDprivate.h | 2 | ||||
-rw-r--r-- | src/H5FDpublic.h | 36 | ||||
-rw-r--r-- | src/H5FS.c | 13 | ||||
-rw-r--r-- | src/H5FSsection.c | 21 | ||||
-rw-r--r-- | src/H5SL.c | 231 | ||||
-rw-r--r-- | src/H5checksum.c | 33 | ||||
-rw-r--r-- | src/H5private.h | 1 |
10 files changed, 667 insertions, 477 deletions
@@ -308,7 +308,7 @@ H5F_get_access_plist(H5F_t *f) /* Copy properties of the file access property list */ if(H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial meta data cache resize config.") + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.") if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME, &(f->shared->rdcc_nelmts)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache element size") if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0) @@ -321,11 +321,11 @@ H5F_get_access_plist(H5F_t *f) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment") if(H5P_set(new_plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set garbage collect reference") - if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->lf->def_meta_block_size)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set meta data cache size") + if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->lf->meta_aggr.alloc_size)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache size") if(H5P_set(new_plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't sieve buffer size") - if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->lf->def_sdata_block_size)) < 0) + if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->lf->sdata_aggr.alloc_size)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'small data' cache size") if(H5P_set(new_plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag") @@ -882,7 +882,7 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) if(NULL == (plist = H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list") if(H5P_get(plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial meta data cache resize config") + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config") if(H5P_get(plist, H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME, &(f->shared->rdcc_nelmts)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache element size") if(H5P_get(plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0) @@ -924,12 +924,12 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) } /* end if */ /* - * Create a meta data cache with the specified number of elements. + * Create a metadata cache with the specified number of elements. * The cache might be created with a different number of elements and * the access property list should be updated to reflect that. */ if(SUCCEED != H5AC_create(f, &(f->shared->mdc_initCacheCfg))) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create meta data cache") + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create metadata cache") /* Create the file's "open object" information */ if(H5FO_create(f) < 0) @@ -1697,12 +1697,12 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags) if(H5D_flush(f, dxpl_id, flags) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache") - /* flush (and invalidate, if requested) the entire meta data cache */ + /* flush (and invalidate, if requested) the entire metadata cache */ H5AC_flags = 0; if((flags & H5F_FLUSH_INVALIDATE) != 0 ) H5AC_flags |= H5AC__FLUSH_INVALIDATE_FLAG; if(H5AC_flush(f, dxpl_id, H5AC_flags) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush meta data cache") + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache") /* * If we are invalidating everything (which only happens just before @@ -1710,29 +1710,11 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags) * "small data" blocks back to the free lists in the file. */ if(flags & H5F_FLUSH_INVALIDATE) { - if(f->shared->lf->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) { - /* Return the unused portion of the metadata block to a free list */ - if(f->shared->lf->eoma != 0) - if(H5FD_free(f->shared->lf, H5FD_MEM_DEFAULT, dxpl_id, - f->shared->lf->eoma, f->shared->lf->cur_meta_block_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free metadata block") - - /* Reset metadata block information, just in case */ - f->shared->lf->eoma = 0; - f->shared->lf->cur_meta_block_size = 0; - } /* end if */ - - if(f->shared->lf->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) { - /* Return the unused portion of the "small data" block to a free list */ - if(f->shared->lf->eosda != 0) - if(H5FD_free(f->shared->lf, H5FD_MEM_DRAW, dxpl_id, - f->shared->lf->eosda, f->shared->lf->cur_sdata_block_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free 'small data' block") + if(H5FD_aggr_reset(f->shared->lf, &(f->shared->lf->meta_aggr), dxpl_id) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't reset metadata block") - /* Reset "small data" block information, just in case */ - f->shared->lf->eosda = 0; - f->shared->lf->cur_sdata_block_size = 0; - } /* end if */ + if(H5FD_aggr_reset(f->shared->lf, &(f->shared->lf->sdata_aggr), dxpl_id) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't reset 'small data' block") } /* end if */ /* Write the superblock to disk */ @@ -60,10 +60,15 @@ static herr_t H5FD_pl_close(hid_t driver_id, herr_t (*free_func)(void *), static herr_t H5FD_free_cls(H5FD_class_t *cls); static haddr_t H5FD_alloc_from_free_list(H5FD_t *file, H5FD_mem_t type, hsize_t size); -static haddr_t H5FD_alloc_metadata(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, - hsize_t size); -static haddr_t H5FD_alloc_raw(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, - hsize_t size); +static haddr_t H5FD_aggr_alloc(H5FD_t *file, H5FD_blk_aggr_t *aggr, + H5FD_blk_aggr_t *other_aggr, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); +static herr_t H5FD_aggr_adjoin(const H5FD_t *file, H5FD_blk_aggr_t *aggr, + H5FD_free_t *last); +static htri_t H5FD_aggr_can_extend(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, + haddr_t eoa, haddr_t end); +static herr_t H5FD_aggr_shift(H5FD_blk_aggr_t *aggr, hsize_t extra); +static herr_t H5FD_aggr_query(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, + haddr_t *addr, hsize_t *size); static haddr_t H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); static herr_t H5FD_free_freelist(H5FD_t *file); static haddr_t H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); @@ -1055,10 +1060,12 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) HDmemset(file->fl, 0, sizeof(file->fl)); if(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(meta_block_size)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get meta data block size") - file->def_meta_block_size = meta_block_size; + file->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA; + file->meta_aggr.alloc_size = meta_block_size; if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(sdata_block_size)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' block size") - file->def_sdata_block_size = sdata_block_size; + file->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA; + file->sdata_aggr.alloc_size = sdata_block_size; file->accum_loc = HADDR_UNDEF; if(H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(file->threshold)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold") @@ -1536,13 +1543,14 @@ HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); if(type != H5FD_MEM_DRAW) { /* Handle metadata differently from "raw" data */ - if((ret_value = H5FD_alloc_metadata(file, type, dxpl_id, size)) == HADDR_UNDEF) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate for metadata") - } else { + if(HADDR_UNDEF == (ret_value = H5FD_aggr_alloc(file, &(file->meta_aggr), &(file->sdata_aggr), type, dxpl_id, size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata") + } /* end if */ + else { /* Allocate "raw" data */ - if((ret_value = H5FD_alloc_raw(file, type, dxpl_id, size)) == HADDR_UNDEF) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate for raw data") - } + if(HADDR_UNDEF == (ret_value = H5FD_aggr_alloc(file, &(file->sdata_aggr), &(file->meta_aggr), type, dxpl_id, size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data") + } /* end else */ done: #ifdef H5FD_ALLOC_DEBUG @@ -1807,8 +1815,8 @@ HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); /*------------------------------------------------------------------------- - * Function: H5FD_alloc_metadata - * Purpose: Try to allocate SIZE bytes of memory from the metadata + * Function: H5FD_aggr_alloc + * Purpose: Try to allocate SIZE bytes of memory from an aggregator * block if possible. * * This is split from H5FD_alloc(). @@ -1816,245 +1824,430 @@ HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); * Failure: The undefined address HADDR_UNDEF * Programmer: Bill Wendling * 2. December, 2002 - * Modifications: * *------------------------------------------------------------------------- */ static haddr_t -H5FD_alloc_metadata(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) +H5FD_aggr_alloc(H5FD_t *file, H5FD_blk_aggr_t *aggr, H5FD_blk_aggr_t *other_aggr, + H5FD_mem_t type, hid_t dxpl_id, hsize_t size) { - haddr_t ret_value = HADDR_UNDEF; + haddr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5FD_alloc_metadata, HADDR_UNDEF) + FUNC_ENTER_NOAPI_NOINIT(H5FD_aggr_alloc) #ifdef H5FD_ALLOC_DEBUG HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); #endif /* H5FD_ALLOC_DEBUG */ /* check args */ - assert(file); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); + HDassert(file); + 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); /* - * If the metadata aggregation feature is enabled for this VFL - * driver, allocate "generic" metadata space and sub-allocate out of + * If the aggregation feature is enabled for this VFL + * driver, allocate "generic" space and sub-allocate out of * that, if possible. Otherwise just allocate through * H5FD_real_alloc() */ + if(file->feature_flags & aggr->feature_flag) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: aggr = {%a, %Hu, %Hu}\n", FUNC, aggr->addr, aggr->tot_size, aggr->size); +#endif /* H5FD_ALLOC_DEBUG */ + /* Check if the space requested is larger than the space left in the block */ + if(size > aggr->size) { + haddr_t new_space; /* Address for newly allocated space */ - /* - * Allocate all types of metadata out of the metadata block - */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) { - /* - * Check if the space requested is larger than the space left in - * the block - */ - if(size > file->cur_meta_block_size) { - haddr_t new_meta; /* Address for new metadata */ - - /* - * Check if the block asked for is too large for a metadata - * block - */ - if(size >= file->def_meta_block_size) { + /* Check if the block asked for is too large for 'normal' aggregator block */ + if(size >= aggr->alloc_size) { /* Allocate more room for this new block the regular way */ - if(HADDR_UNDEF==(new_meta = H5FD_real_alloc(file, type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata block") + if(HADDR_UNDEF == (new_space = H5FD_real_alloc(file, type, dxpl_id, size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block") - /* - * Check if the new metadata is at the end of the current - * metadata block - */ - if(file->eoma + file->cur_meta_block_size == new_meta) { + /* Check if the new space is at the end of the current block */ + if((aggr->addr + aggr->size) == new_space) { /* - * Treat the allocation request as if the current - * metadata block grew by the amount allocated and - * just update the eoma address. Don't bother - * updating the cur_meta_block_size since it will + * Treat the allocation request as if the current block + * grew by the amount allocated and just update the address. + * + * Don't bother updating the block's size since it will * just grow and shrink by the same amount. + * + * _Do_ add to the total size aggregated. + * */ - ret_value = file->eoma; - file->eoma += size; - } else { - /* Use the new metadata block for the space allocated */ - ret_value = new_meta; - } - } else { - /* Allocate another metadata block */ + ret_value = aggr->addr; + aggr->addr += size; + aggr->tot_size += size; + } /* end if */ + else { + /* Check if the new space is at the end of the _other_ block */ + if(other_aggr->size > 0 && (other_aggr->addr + other_aggr->size) == new_space) { #ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Allocating 'metadata' block\n", FUNC); +HDfprintf(stderr, "%s: New block is at end of 'other' block: other_aggr = {%a, %Hu, %Hu}\n", FUNC, other_aggr->addr, other_aggr->tot_size, other_aggr->size); #endif /* H5FD_ALLOC_DEBUG */ - if(HADDR_UNDEF==(new_meta = H5FD_real_alloc(file, H5FD_MEM_DEFAULT, dxpl_id, - file->def_meta_block_size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata block") + /* If the other block has used at least the + * 'allocation' amount for that block, shift the + * newly allocated space down over the remainder + * in the 'other block', shift the 'other block' + * up by the same amount and free it. (Which + * should amount to "bubbling" the remainder in + * the 'other block' to the end of the file and + * then "popping" the bubble by shrinking the + * file) + */ + if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) { + H5FD_mem_t alloc_type = (other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ + haddr_t free_addr = (new_space + size) - other_aggr->size; /* Address of free space in 'other block' shifted toward end of the file */ + hsize_t free_size = other_aggr->size; /* Size of the free space in 'other block' */ - /* - * Check if the new metadata is at the end of the current - * metadata block - */ - if(file->eoma + file->cur_meta_block_size == new_meta) { - file->cur_meta_block_size += file->def_meta_block_size; - } else { - /* - * Return the unused portion of the metadata block to - * a free list - */ - if(file->eoma != 0) - if(H5FD_free(file, H5FD_MEM_DEFAULT, dxpl_id, file->eoma, - file->cur_meta_block_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free metadata block") - - /* Point the metadata block at the newly allocated block */ - file->eoma = new_meta; - file->cur_meta_block_size = file->def_meta_block_size; - } +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Freeing 'other' block\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ + /* Reset 'other' block's info */ + other_aggr->addr = 0; + other_aggr->tot_size = 0; + other_aggr->size = 0; + + /* Shift newly allocated space down */ + new_space -= free_size; + + /* Return the unused portion of the 'other' block to a free list */ + if(H5FD_free(file, alloc_type, dxpl_id, free_addr, free_size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") + } /* end if */ + } /* end if */ + + /* Use the new space allocated, leaving the old block */ + ret_value = new_space; + } /* end else */ + } /* end if */ + else { + H5FD_mem_t alloc_type = (aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ + + /* Allocate another block */ +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Allocating block\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ + if(HADDR_UNDEF == (new_space = H5FD_real_alloc(file, alloc_type, dxpl_id, aggr->alloc_size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block") + + /* Check if the new space is at the end of the current block */ + if(aggr->addr + aggr->size == new_space) { + aggr->size += aggr->alloc_size; + aggr->tot_size += aggr->alloc_size; + } /* end if */ + else { + hsize_t new_size; /* Size of new aggregator block */ + + /* Return the unused portion of the block to a free list */ + if(aggr->size > 0) + if(H5FD_free(file, alloc_type, dxpl_id, aggr->addr, aggr->size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") + + /* Check if the new space is at the end of the _other_ block */ + if(other_aggr->size > 0 && (other_aggr->addr + other_aggr->size) == new_space) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: New block is at end of 'other' block: other_aggr = {%a, %Hu, %Hu}\n", FUNC, other_aggr->addr, other_aggr->tot_size, other_aggr->size); +#endif /* H5FD_ALLOC_DEBUG */ +#ifdef QAK + /* If the other block has used at least the + * 'allocation' amount for that block, give the + * remaining free space in the 'other' block to + * the new space allocated for 'this' block. + */ + if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Absorbing 'other' block\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ + /* Absorb the remaining free space into newly allocated block */ + new_space -= other_aggr->size; + new_size = aggr->alloc_size + other_aggr->size; + + /* Reset the info for the 'other' block */ + other_aggr->addr = 0; + other_aggr->tot_size = 0; + other_aggr->size = 0; + } /* end if */ + else + new_size = aggr->alloc_size; +#else /* QAK */ + /* If the other block has used at least the + * 'allocation' amount for that block, shift the + * newly allocated space down over the remainder + * in the 'other block', shift the 'other block' + * up by the same amount and free it. (Which + * should amount to "bubbling" the remainder in + * the 'other block' to the end of the file and + * then "popping" the bubble by shrinking the + * file) + */ + if((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size) { + H5FD_mem_t other_type = (other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ + haddr_t free_addr = (new_space + aggr->alloc_size) - other_aggr->size; /* Address of free space in 'other block' shifted toward end of the file */ + hsize_t free_size = other_aggr->size; /* Size of the free space in 'other block' */ + +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Freeing 'other' block\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ + /* Reset 'other' block's info */ + other_aggr->addr = 0; + other_aggr->tot_size = 0; + other_aggr->size = 0; + + /* Shift newly allocated space down */ + new_space -= free_size; + + /* Return the unused portion of the 'other' block to a free list */ + if(H5FD_free(file, other_type, dxpl_id, free_addr, free_size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block") + } /* end if */ + new_size = aggr->alloc_size; +#endif /* QAK */ + } /* end if */ + else + new_size = aggr->alloc_size; + + /* Point the aggregator at the newly allocated block */ + aggr->addr = new_space; + aggr->size = new_size; + aggr->tot_size = new_size; + } /* end else */ /* Allocate space out of the metadata block */ - ret_value = file->eoma; - file->cur_meta_block_size -= size; - file->eoma += size; - } - } else { - /* Allocate space out of the metadata block */ - ret_value = file->eoma; - file->cur_meta_block_size -= size; - file->eoma += size; + ret_value = aggr->addr; + aggr->size -= size; + aggr->addr += size; + } /* end else */ + } /* end if */ + else { + /* Allocate space out of the block */ + ret_value = aggr->addr; + aggr->size -= size; + aggr->addr += size; } - } else { + } /* end if */ + else { /* Allocate data the regular way */ - if(HADDR_UNDEF==(ret_value = H5FD_real_alloc(file, type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata block") - } + if(HADDR_UNDEF == (ret_value = H5FD_real_alloc(file, type, dxpl_id, size))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate file space") + } /* end else */ done: #ifdef H5FD_ALLOC_DEBUG HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); #endif /* H5FD_ALLOC_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_alloc_metadata() */ +} /* end H5FD_aggr_alloc() */ /*------------------------------------------------------------------------- - * Function: H5FD_alloc_raw - * Purpose: Try to allocate SIZE bytes of raw data. + * Function: H5FD_aggr_adjoin + * + * Purpose: Check if a newly freed block of space in the file adjoins an + * aggregator block + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 * - * This is split from H5FD_alloc(). - * Return: Success: The format address of the new file memory. - * Failure: The undefined address HADDR_UNDEF - * Programmer: Bill Wendling - * 2. December, 2002 - * Modifications: *------------------------------------------------------------------------- */ -static haddr_t -H5FD_alloc_raw(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size) +static herr_t +H5FD_aggr_adjoin(const H5FD_t *file, H5FD_blk_aggr_t *aggr, H5FD_free_t *last) { - haddr_t ret_value = HADDR_UNDEF; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_adjoin) + + /* Check args */ + HDassert(file); + HDassert(file->cls); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + HDassert(last); + + /* Check if this free block adjoins the aggregator */ + if((file->feature_flags & aggr->feature_flag) && aggr->size > 0) { + hbool_t adjoins = FALSE; /* Whether the block adjoined the aggregator */ + + /* Does the newly freed space adjoin the end of the aggregator */ + if((aggr->addr + aggr->size) == last->addr) { + last->addr = aggr->addr; + adjoins = TRUE; + } /* end if */ + /* Does the newly freed space adjoin the beginning of the aggregator */ + else if((last->addr + last->size) == aggr->addr) + adjoins = TRUE; - FUNC_ENTER_NOAPI(H5FD_alloc_raw, HADDR_UNDEF) + /* Reset aggregator information, if adjoined */ + if(adjoins) { #ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size); +HDfprintf(stderr, "%s: Adjoined flag = %lx aggregator\n", "H5FD_aggr_adjoin", aggr->feature_flag); #endif /* H5FD_ALLOC_DEBUG */ + last->size += aggr->size; + aggr->addr = 0; + aggr->size = 0; + } /* end if */ + } /* end if */ - /* check args */ - assert(file); - assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); - assert(size > 0); + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5FD_aggr_adjoin() */ - /* - * If the "small data" aggregation feature is enabled for this VFL driver, - * allocate "small data" space and sub-allocate out of that, if - * possible. Otherwise just allocate through H5FD_real_alloc() - */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) { - /* - * Check if the space requested is larger than the space left in - * the block + +/*------------------------------------------------------------------------- + * Function: H5FD_aggr_can_extend + * + * Purpose: Check is an aggregator block can be extended + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5FD_aggr_can_extend(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, haddr_t eoa, + haddr_t end) +{ + htri_t ret_value = FALSE; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_can_extend) + + /* Check args */ + HDassert(file); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + + /* Check if this aggregator is active */ + if(file->feature_flags & aggr->feature_flag) { + /* If the aggregator block is at the end of the file, and the block to + * test adjoins the beginning of the aggregator block, then it's + * extendable */ - if(size > file->cur_sdata_block_size) { - haddr_t new_data; /* Address for new raw data block */ + if((aggr->addr + aggr->size) == eoa && end == aggr->addr) + HGOTO_DONE(TRUE) + } /* end if */ - /* Check if the block asked for is too large for the "small data" block */ - if(size >= file->def_sdata_block_size) { - /* Allocate more room for this new block the regular way */ - if(HADDR_UNDEF==(new_data = H5FD_real_alloc(file, type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data block") +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_aggr_can_extend() */ - /* - * Check if the new raw data is at the end of the current - * "small data" block - */ - if(file->eosda + file->cur_sdata_block_size == new_data) { - /* - * Treat the allocation request as if the current - * "small data" block grew by the amount allocated - * and just update the eosda address. Don't bother - * updating the cur_sdata_block_size since it will - * just grow and shrink by the same amount. - */ - ret_value = file->eosda; - file->eosda += size; - } else { - /* Use the new "small data" block for the space allocated */ - ret_value = new_data; - } - } else { - /* Allocate another "small data" block */ -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Allocating 'small data' block\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - if(HADDR_UNDEF==(new_data = H5FD_real_alloc(file, type, dxpl_id, - file->def_sdata_block_size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data block") + +/*------------------------------------------------------------------------- + * Function: H5FD_aggr_extend + * + * Purpose: Shift an aggregator block in the file + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_aggr_shift(H5FD_blk_aggr_t *aggr, hsize_t extra) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_shift) - /* - * Check if the new raw data is at the end of the current - * "small data" block - */ - if(file->eosda + file->cur_sdata_block_size == new_data) { - file->cur_sdata_block_size += file->def_sdata_block_size; - } else { - /* - * Return the unused portion of the "small data" - * block to a free list - */ - if(file->eosda != 0) - if(H5FD_free(file, H5FD_MEM_DRAW, dxpl_id, file->eosda, - file->cur_sdata_block_size) < 0) - HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free 'small data' block") + /* Check args */ + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); - /* - * Point the "small data" block at the newly - * allocated block - */ - file->eosda = new_data; - file->cur_sdata_block_size = file->def_sdata_block_size; - } + /* Shift the aggregator block by the extra amount */ + aggr->addr += extra; - /* Allocate space out of the "small data" block */ - ret_value = file->eosda; - file->cur_sdata_block_size -= size; - file->eosda += size; - } - } else { - /* Allocate space out of the "small data" block */ - ret_value = file->eosda; - file->cur_sdata_block_size -= size; - file->eosda += size; - } - } else { - /* Allocate data the regular way */ - if(HADDR_UNDEF==(ret_value = H5FD_real_alloc(file, type, dxpl_id, size))) - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data block") - } + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5FD_aggr_shift() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_aggr_query + * + * Purpose: Query a block aggregator's current address & size info + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_aggr_query(const H5FD_t *file, const H5FD_blk_aggr_t *aggr, haddr_t *addr, + hsize_t *size) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_aggr_query) + + /* Check args */ + HDassert(file); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + + /* Check if this aggregator is active */ + if(file->feature_flags & aggr->feature_flag) { + *addr = aggr->addr; + *size = aggr->size; + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5FD_aggr_query() */ + + +/*------------------------------------------------------------------------- + * Function: H5FD_aggr_reset + * + * Purpose: Reset a block aggregator, returning any space back to file + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, December 13, 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FD_aggr_reset(H5FD_t *file, H5FD_blk_aggr_t *aggr, hid_t dxpl_id) +{ + H5FD_mem_t alloc_type; /* Type of file memory to work with */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FD_aggr_reset, FAIL) + + /* Check args */ + HDassert(file); + HDassert(aggr); + HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA); + + /* Set the type of memory in the file */ + alloc_type = (aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */ + + /* Check if this aggregator is active */ + if(file->feature_flags & aggr->feature_flag) { + /* Return the unused portion of the metadata block to a free list */ + if(aggr->size > 0) + if(H5FD_free(file, alloc_type, dxpl_id, aggr->addr, aggr->size) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free aggregator block") + + /* Reset aggregator block information */ + aggr->tot_size = 0; + aggr->addr = 0; + aggr->size = 0; + } /* end if */ done: -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value); -#endif /* H5FD_ALLOC_DEBUG */ FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_alloc_raw() */ +} /* end H5FD_aggr_reset() */ /*------------------------------------------------------------------------- @@ -2248,18 +2441,11 @@ done: * Purpose: Private version of H5FDfree() * * Return: Success: Non-negative - * * Failure: Negative * * Programmer: Robb Matzke * Wednesday, August 4, 1999 * - * Modifications: - * Bill Wendling, February 20, 2003 - * Added support for Flexible PHDF5. If the process is the - * Set-Aside-Process, then we execute this function. Clients - * don't. - * *------------------------------------------------------------------------- */ herr_t @@ -2269,15 +2455,16 @@ H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t si herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5FD_free, FAIL) -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size); -#endif /* H5FD_ALLOC_DEBUG */ /* Check args */ HDassert(file); HDassert(file->cls); HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES); +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size); +#endif /* H5FD_ALLOC_DEBUG */ + if(!H5F_addr_defined(addr) || addr > file->maxaddr || H5F_addr_overflow(addr, size) || (addr + size) > file->maxaddr) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid region") @@ -2291,6 +2478,9 @@ HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type mapped_type = type; else mapped_type = file->cls->fl_map[type]; +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: mapped_type = %u\n", FUNC, (unsigned)mapped_type); +#endif /* H5FD_ALLOC_DEBUG */ /* * If the request maps to a free list then add memory to the free list @@ -2454,57 +2644,20 @@ HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type last->next = file->fl[mapped_type]; file->fl[mapped_type] = last; } /* end else */ +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: mapped_type = %u, last = {%a, %Hu}\n", FUNC, (unsigned)mapped_type, last->addr, last->size); +#endif /* H5FD_ALLOC_DEBUG */ /* Check if we increased the size of the largest block on the list */ file->maxsize = MAX(file->maxsize, last->size); /* Check if this free block adjoins the "metadata aggregator" */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA && file->eoma != 0) { - hbool_t adjoins = FALSE; /* Whether the block adjoined the metadata aggregator */ - - /* Does the new block adjoin the end of the metadata aggregator */ - if((file->eoma + file->cur_meta_block_size) == last->addr) { - last->addr = file->eoma; - adjoins = TRUE; - } /* end if */ - /* Does the new block adjoin the beginning of the metadata aggregator */ - else if((last->addr + last->size) == file->eoma) - adjoins = TRUE; - - /* Reset metadata aggregator information, if adjoined */ - if(adjoins) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Adjoined metadata aggregator\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - last->size += file->cur_meta_block_size; - file->eoma = 0; - file->cur_meta_block_size = 0; - } /* end if */ - } /* end if */ + if(H5FD_aggr_adjoin(file, &(file->meta_aggr), last) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "aggregator deallocation request failed") /* Check if this free block adjoins the "small data aggregator" */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA && file->eosda != 0) { - hbool_t adjoins = FALSE; /* Whether the block adjoined the small-data aggregator */ - - /* Does the new block adjoin the end of the small-data aggregator */ - if((file->eosda + file->cur_sdata_block_size) == last->addr) { - last->addr = file->eosda; - adjoins = TRUE; - } /* end if */ - /* Does the new block adjoin the beginning of the small-data aggregator */ - else if((last->addr + last->size) == file->eosda) - adjoins = TRUE; - - /* Reset small-data aggregator information, if adjoined */ - if(adjoins) { -#ifdef H5FD_ALLOC_DEBUG -HDfprintf(stderr, "%s: Adjoined small data aggregator\n", FUNC); -#endif /* H5FD_ALLOC_DEBUG */ - last->size += file->cur_sdata_block_size; - file->eosda = 0; - file->cur_sdata_block_size = 0; - } /* end if */ - } /* end if */ + if(H5FD_aggr_adjoin(file, &(file->sdata_aggr), last) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "aggregator deallocation request failed") /* Check if this free block is at the end of file allocated space. * Truncate it if this is true. */ @@ -2512,6 +2665,9 @@ HDfprintf(stderr, "%s: Adjoined small data aggregator\n", FUNC); haddr_t eoa; eoa = file->cls->get_eoa(file, type); +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: eoa = %a\n", FUNC, eoa); +#endif /* H5FD_ALLOC_DEBUG */ if(eoa == (last->addr + last->size)) { #ifdef H5FD_ALLOC_DEBUG HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, last->addr); @@ -2527,13 +2683,16 @@ HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, last->addr); } /* end if */ } /* end if */ } else if(file->cls->free) { +#ifdef H5FD_ALLOC_DEBUG +HDfprintf(stderr, "%s: Letting VFD free space\n", FUNC); +#endif /* H5FD_ALLOC_DEBUG */ if((file->cls->free)(file, type, dxpl_id, addr, size) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver free request failed") } else { /* leak memory */ -#ifdef H5F_DEBUG +#ifdef H5FD_ALLOC_DEBUG HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size); -#endif /* H5F_DEBUG */ +#endif /* H5FD_ALLOC_DEBUG */ } /* end else */ done: @@ -2684,22 +2843,25 @@ done: htri_t H5FD_can_extend(const H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested) { - haddr_t eoa; /* End of address space in the file */ - htri_t ret_value=FALSE; /* Return value */ + haddr_t end; /* End of block in file */ + haddr_t eoa; /* End of address space in the file */ + htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI(H5FD_can_extend, FAIL) /* Retrieve the end of the address space */ - if(HADDR_UNDEF==(eoa=H5FD_get_eoa(file, type))) + if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file, type))) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed") + /* Compute end of block */ + end = addr + size; + /* Check if the block is exactly at the end of the file */ - if((addr+size)==eoa) + if(end == eoa) HGOTO_DONE(TRUE) else { H5FD_free_t *curr; /* Current free block being inspected */ H5FD_mem_t mapped_type; /* Memory type, after mapping */ - haddr_t end; /* End of block in file */ /* Map request type to free list */ if(H5FD_MEM_DEFAULT==file->cls->fl_map[type]) @@ -2707,34 +2869,25 @@ H5FD_can_extend(const H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, else mapped_type = file->cls->fl_map[type]; - /* Check if block is inside the metadata or small data accumulator */ + /* Check if block is inside the metadata or small data aggregator */ if(mapped_type!=H5FD_MEM_DRAW) { - if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) { - /* If the metadata block is at the end of the file, and - * the block to test adjoins the beginning of the metadata - * block, then it's extendable - */ - if(file->eoma + file->cur_meta_block_size == eoa && - (addr+size)==file->eoma) - HGOTO_DONE(TRUE) - } /* end if */ + /* Check for test block able to extend metadata aggregation block */ + if((ret_value = H5FD_aggr_can_extend(file, &(file->meta_aggr), eoa, end)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended") + else if(ret_value > 0) + HGOTO_DONE(TRUE) } /* end if */ else { - if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) { - /* If the small data block is at the end of the file, and - * the block to test adjoins the beginning of the small data - * block, then it's extendable - */ - if(file->eosda + file->cur_sdata_block_size == eoa && - (addr+size)==file->eosda) - HGOTO_DONE(TRUE) - } /* end if */ + /* Check for test block able to extend metadata aggregation block */ + if((ret_value = H5FD_aggr_can_extend(file, &(file->sdata_aggr), eoa, end)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if 'small data' aggregation block can be extended") + else if(ret_value > 0) + HGOTO_DONE(TRUE) } /* end else */ /* Scan through the existing blocks for the mapped type to see if we can extend one */ if(mapped_type >= H5FD_MEM_DEFAULT) { curr = file->fl[mapped_type]; - end = addr + size; while(curr != NULL) { if(end == curr->addr) { if(extra_requested <= curr->size) @@ -2805,24 +2958,18 @@ HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n else { /* (Check if block is inside the metadata or small data accumulator) */ if(mapped_type!=H5FD_MEM_DRAW) { - if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) - /* If the metadata block is at the end of the file, and - * the block to test adjoins the beginning of the metadata - * block, then it's extendable - */ - if((file->eoma + file->cur_meta_block_size) == eoa && - end == file->eoma) - update_eoma=TRUE; + /* Check for test block able to extend metadata aggregation block */ + if((ret_value = H5FD_aggr_can_extend(file, &(file->meta_aggr), eoa, end)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended") + else if(ret_value > 0) + update_eoma = TRUE; } /* end if */ else { - if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) - /* If the small data block is at the end of the file, and - * the block to test adjoins the beginning of the small data - * block, then it's extendable - */ - if((file->eosda + file->cur_sdata_block_size) == eoa && - end == file->eosda) - update_eosda=TRUE; + /* Check for test block able to extend metadata aggregation block */ + if((ret_value = H5FD_aggr_can_extend(file, &(file->sdata_aggr), eoa, end)) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't determine if metadata aggregation block can be extended") + else if(ret_value > 0) + update_eosda = TRUE; } /* end else */ } /* end else */ @@ -2838,11 +2985,11 @@ HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "file allocation request failed") /* Update the metadata and/or small data block */ - assert(!(update_eoma && update_eosda)); + HDassert(!(update_eoma && update_eosda)); if(update_eoma) - file->eoma+=extra_requested; + H5FD_aggr_shift(&(file->meta_aggr), extra_requested); if(update_eosda) - file->eosda+=extra_requested; + H5FD_aggr_shift(&(file->sdata_aggr), extra_requested); } /* end if */ /* If the block we are extending isn't at the end of the file, find a free block to extend into */ else { @@ -3927,17 +4074,11 @@ H5FD_get_freespace(const H5FD_t *file) /* Retrieve the 'eoa' for the file */ eoa = file->cls->get_eoa(file, H5FD_MEM_DEFAULT); - /* Check for aggregating metadata allocations */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) { - ma_addr = file->eoma; - ma_size = file->cur_meta_block_size; - } /* end if */ + /* Retrieve metadata aggregator info, if available */ + H5FD_aggr_query(file, &(file->meta_aggr), &ma_addr, &ma_size); - /* Check for aggregating small data allocations */ - if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) { - sda_addr = file->eosda; - sda_size = file->cur_sdata_block_size; - } /* end if */ + /* Retrieve 'small data' aggregator info, if available */ + H5FD_aggr_query(file, &(file->sdata_aggr), &sda_addr, &sda_size); /* Iterate over all the types of memory, to retrieve amount of free space for each */ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t,type)) { @@ -3962,7 +4103,7 @@ H5FD_get_freespace(const H5FD_t *file) } /* end for */ /* Check for aggregating metadata allocations */ - if(H5F_addr_defined(ma_addr)) { + 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)) @@ -3970,7 +4111,7 @@ H5FD_get_freespace(const H5FD_t *file) } /* end if */ /* Check for aggregating small data allocations */ - if(H5F_addr_defined(sda_addr)) { + if(sda_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(sda_addr + sda_size, eoa)) diff --git a/src/H5FDlog.c b/src/H5FDlog.c index 3109e09..df07c0a 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -234,7 +234,11 @@ static const H5FD_class_t H5FD_log_g = { H5FD_log_flush, /*flush */ NULL, /*lock */ NULL, /*unlock */ +#ifdef OLD_WAY H5FD_FLMAP_NOLIST /*fl_map */ +#else /* OLD_WAY */ + H5FD_FLMAP_SINGLE /*fl_map */ +#endif /* OLD_WAY */ }; diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h index 202b7d1..6f3a8de 100644 --- a/src/H5FDprivate.h +++ b/src/H5FDprivate.h @@ -74,5 +74,7 @@ H5_DLL htri_t H5FD_can_extend(const H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested); H5_DLL herr_t H5FD_extend(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested); +H5_DLL herr_t H5FD_aggr_reset(H5FD_t *file, H5FD_blk_aggr_t *aggr, hid_t dxpl_id); #endif /* !_H5FDprivate_H */ + diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index ebf006b..ea92649 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -222,6 +222,15 @@ typedef struct H5FD_free_t { struct H5FD_free_t *next; } H5FD_free_t; +/* Structure for metadata & "small [raw] data" block aggregation fields */ +typedef struct H5FD_blk_aggr_t { + unsigned long feature_flag; /* Feature flag type */ + hsize_t alloc_size; /* Size for allocating new blocks */ + hsize_t tot_size; /* Total amount of bytes aggregated into block */ + hsize_t size; /* Current size of block left */ + haddr_t addr; /* Location of block left */ +} H5FD_blk_aggr_t; + /* * The main datatype for each driver. Public fields common to all drivers * are declared here and the driver appends private fields in memory. @@ -234,27 +243,11 @@ struct H5FD_t { hsize_t threshold; /* Threshold for alignment */ hsize_t alignment; /* Allocation alignment */ - /* Metadata aggregation fields */ - hsize_t def_meta_block_size; /* Metadata allocation - * block size (if - * aggregating metadata) */ - hsize_t cur_meta_block_size; /* Current size of metadata - * allocation region left */ - haddr_t eoma; /* End of metadata - * allocated region */ - /* (ie. beginning of space available) */ - - /* "Small data" aggregation fields */ - hsize_t def_sdata_block_size; /* "Small data" - * allocation block size - * (if aggregating "small - * data") */ - hsize_t cur_sdata_block_size; /* Current size of "small - * data" allocation - * region left */ - haddr_t eosda; /* End of "small data" - * allocated region */ - /* (ie. beginning of space available) */ + /* Block aggregation info */ + H5FD_blk_aggr_t meta_aggr; /* Metadata aggregation info */ + /* (if aggregating metadata allocations) */ + H5FD_blk_aggr_t sdata_aggr; /* "Small data" aggregation info */ + /* (if aggregating "small data" allocations) */ /* Metadata accumulator fields */ unsigned char *meta_accum; /* Buffer to hold the accumulated metadata */ @@ -304,3 +297,4 @@ H5_DLL herr_t H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing); } #endif #endif + @@ -101,6 +101,9 @@ H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_c H5FS_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5FS_create, NULL) +#ifdef QAK +HDfprintf(stderr, "%s: Creating free space manager, nclasses = %Zu\n", FUNC, nclasses); +#endif /* QAK */ /* Check arguments. */ HDassert(fs_addr); @@ -373,13 +376,13 @@ HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_c else { unsigned sect_status = 0; /* Free space section's status in the metadata cache */ - /* Check the free space section's status in the metadata cache */ - if(H5AC_get_entry_status(f, fspace->sect_addr, §_status) < 0) + /* Check if we've allocated any section info in the file & if it's still in the cache */ + if(H5F_addr_defined(fspace->sect_addr) && H5AC_get_entry_status(f, fspace->sect_addr, §_status) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "unable to check metadata cache status for free space header") - /* If this free list header's section info is still in the cache, don't - * unpin the header - let the section info do it, when the section - * into is evicted from the cache. -QAK + /* If this free list header's section info exists and is still in the + * cache, don't unpin the header - let the section info do it, + * when the section info is evicted from the cache. -QAK */ if(!(sect_status & H5AC_ES__IN_CACHE)) { /* Unpin the free space header in the cache */ diff --git a/src/H5FSsection.c b/src/H5FSsection.c index 505223a..c589aa0 100644 --- a/src/H5FSsection.c +++ b/src/H5FSsection.c @@ -187,6 +187,9 @@ H5FS_sinfo_pin(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) H5FS_sinfo_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5FS_sinfo_pin) +#ifdef QAK +HDfprintf(stderr, "%s: Called, fspace->sect_addr = %a\n", FUNC, fspace->sect_addr); +#endif /* QAK */ /* Check arguments. */ HDassert(f); @@ -194,6 +197,9 @@ H5FS_sinfo_pin(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) /* Create new section info, if it doesn't exist yet */ if(!H5F_addr_defined(fspace->sect_addr)) { +#ifdef QAK +HDfprintf(stderr, "%s: Allocating new section info\n", FUNC); +#endif /* QAK */ /* Sanity check */ HDassert(fspace->tot_sect_count == 0); HDassert(fspace->serial_sect_count == 0); @@ -208,6 +214,9 @@ H5FS_sinfo_pin(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) fspace->alloc_sect_size = (size_t)fspace->sect_size; if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->alloc_sect_size))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, NULL, "file allocation failed for free space sections") +#ifdef QAK +HDfprintf(stderr, "%s: New section info, addr = %a, size = %Hu\n", FUNC, fspace->sect_addr, fspace->alloc_sect_size); +#endif /* QAK */ /* Cache the new free space section info (pinned) */ if(H5AC_set(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, sinfo, H5AC__PIN_ENTRY_FLAG) < 0) @@ -1209,12 +1218,6 @@ HDfprintf(stderr, "%s: request = %Hu\n", FUNC, request); HDassert(request); HDassert(node); - /* Check if we need to go get the sections */ - if(fspace->sinfo == NULL) { - if(NULL == (fspace->sinfo = H5FS_sinfo_pin(f, dxpl_id, fspace))) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't pin sections") - } /* end if */ - /* Check for any sections on free space list */ #ifdef QAK HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count); @@ -1222,6 +1225,12 @@ HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", FUNC, fspace->serial_ HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", FUNC, fspace->ghost_sect_count); #endif /* QAK */ if(fspace->tot_sect_count > 0) { + /* Check if we need to go get the sections */ + if(fspace->sinfo == NULL) { + if(NULL == (fspace->sinfo = H5FS_sinfo_pin(f, dxpl_id, fspace))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't pin sections") + } /* end if */ + /* Look for node in bins */ if((ret_value = H5FS_sect_find_node(fspace, request, node)) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from bins") @@ -90,69 +90,93 @@ #define H5SL_LOCATE_FIND_FOUND(SLIST,X,UPDATE,I) \ HGOTO_DONE(X); -/* Define a code template for updating the "update" vector for the "DOUPDATE" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_YES_UPDATE(X,UPDATE,I) \ - UPDATE[I]=&X->forward[I]; -/* Define a code template for _NOT_ updating the "update" vector for the "DOUPDATE" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_NO_UPDATE(X,UPDATE,I) +/* Define a code template for "OP"s that update the "update" vector for the H5SL_LOCATE macro */ +#define H5SL_LOCATE_INSERT_UPDATE(X, UPDATE, I) \ + UPDATE[I] = &X->forward[I]; +#define H5SL_LOCATE_REMOVE_UPDATE(X, UPDATE, I) \ + UPDATE[I] = &X->forward[I]; + +/* Define a code template for "OP"s that _DON'T_ update the "update" vector for the H5SL_LOCATE macro */ +#define H5SL_LOCATE_SEARCH_UPDATE(X, UPDATE, I) +#define H5SL_LOCATE_FIND_UPDATE(X, UPDATE, I) + /* Define a code template for comparing scalar keys for the "CMP" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_SCALAR_CMP(TYPE,PKEY1,PKEY2) \ - (*(TYPE *)PKEY1 < *(TYPE *)PKEY2) +#define H5SL_LOCATE_SCALAR_CMP(TYPE, PNODE, PKEY, HASHVAL) \ + (*(TYPE *)((PNODE)->key) < *(TYPE *)PKEY) /* Define a code template for comparing string keys for the "CMP" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_STRING_CMP(TYPE,PKEY1,PKEY2) \ - (HDstrcmp(PKEY1, PKEY2) < 0) +#define H5SL_LOCATE_STRING_CMP(TYPE, PNODE, PKEY, HASHVAL) \ + (((PNODE)->hashval == HASHVAL) ? (HDstrcmp((PNODE)->key, PKEY) < 0) : ((PNODE)->hashval < HASHVAL)) /* Define a code template for comparing H5_obj_t keys for the "CMP" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_OBJ_CMP(TYPE,PKEY1,PKEY2) \ - ((((TYPE *)PKEY1)->fileno < ((TYPE *)PKEY2)->fileno) ? TRUE : (((TYPE *)PKEY1)->addr < ((TYPE *)PKEY2)->addr)) +#define H5SL_LOCATE_OBJ_CMP(TYPE, PNODE, PKEY, HASHVAL) \ + ((((TYPE *)((PNODE)->key))->fileno < ((TYPE *)PKEY)->fileno) ? TRUE : (((TYPE *)((PNODE)->key))->addr < ((TYPE *)PKEY)->addr)) + /* Define a code template for comparing scalar keys for the "EQ" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_SCALAR_EQ(TYPE,PKEY1,PKEY2) \ - (*(TYPE *)PKEY1 == *(TYPE *)PKEY2) +#define H5SL_LOCATE_SCALAR_EQ(TYPE, PNODE, PKEY, HASHVAL) \ + (*(TYPE *)((PNODE)->key) == *(TYPE *)PKEY) /* Define a code template for comparing string keys for the "EQ" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_STRING_EQ(TYPE,PKEY1,PKEY2) \ - (HDstrcmp(PKEY1, PKEY2) == 0) +#define H5SL_LOCATE_STRING_EQ(TYPE, PNODE, PKEY, HASHVAL) \ + (((PNODE)->hashval == HASHVAL) && (HDstrcmp(((PNODE)->key), PKEY) == 0)) + +/* Define a code template for comparing H5_obj_t keys for the "EQ" in the H5SL_LOCATE macro */ +#define H5SL_LOCATE_OBJ_EQ(TYPE, PNODE, PKEY, HASHVAL) \ + ((((TYPE *)((PNODE)->key))->fileno == ((TYPE *)PKEY)->fileno) && (((TYPE *)((PNODE)->key))->addr == ((TYPE *)PKEY)->addr)) + + +/* Define a code template for initializing the hash value for scalar keys for the "HASHINIT" in the H5SL_LOCATE macro */ +#define H5SL_LOCATE_SCALAR_HASHINIT(KEY, HASHVAL) + +/* Define a code template for initializing the hash value for string keys for the "HASHINIT" in the H5SL_LOCATE macro */ +#define H5SL_LOCATE_STRING_HASHINIT(KEY, HASHVAL) \ + HASHVAL = H5_hash_string(KEY); + +/* Define a code template for initializing the hash value for H5_obj_t keys for the "HASHINIT" in the H5SL_LOCATE macro */ +#define H5SL_LOCATE_OBJ_HASHINIT(KEY, HASHVAL) -/* Define a code template for comparing H5_obj_ keys for the "EQ" in the H5SL_LOCATE macro */ -#define H5SL_LOCATE_OBJ_EQ(TYPE,PKEY1,PKEY2) \ - ((((TYPE *)PKEY1)->fileno == ((TYPE *)PKEY2)->fileno) && (((TYPE *)PKEY1)->addr == ((TYPE *)PKEY2)->addr)) /* Macro used to find node for operation */ -#define H5SL_LOCATE(OP,DOUPDATE,CMP,SLIST,X,UPDATE,I,TYPE,KEY,CHECKED) \ - CHECKED=NULL; \ - for(I=(int)SLIST->curr_level; I>=0; I--) { \ - if(X->forward[I]!=CHECKED) { \ - while(X->forward[I] && H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE,X->forward[I]->key,KEY) ) \ - X=X->forward[I]; \ - CHECKED=X->forward[I]; \ +#define H5SL_LOCATE(OP, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \ +{ \ + H5SL_node_t *_checked; /* Pointer to last node checked */ \ + int _i; /* Local index variable */ \ + \ + _checked = NULL; \ + H5_GLUE3(H5SL_LOCATE_,CMP,_HASHINIT)(KEY, HASHVAL) \ + for(_i = (int)SLIST->curr_level; _i >= 0; _i--) { \ + if(X->forward[_i] != _checked) { \ + while(X->forward[_i] && H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE, X->forward[_i], KEY, HASHVAL) ) \ + X = X->forward[_i]; \ + _checked = X->forward[_i]; \ } /* end if */ \ - H5_GLUE3(H5SL_LOCATE_,DOUPDATE,_UPDATE)(X,UPDATE,I) \ + H5_GLUE3(H5SL_LOCATE_,OP,_UPDATE)(X, UPDATE, _i) \ } /* end for */ \ - X=X->forward[0]; \ - if(X!=NULL && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(TYPE,X->key,KEY) ) { \ + X = X->forward[0]; \ + if(X != NULL && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(TYPE, X, KEY, HASHVAL) ) { \ /* What to do when a node is found */ \ - H5_GLUE3(H5SL_LOCATE_,OP,_FOUND)(SLIST,X,UPDATE,I) \ - } /* end if */ + H5_GLUE3(H5SL_LOCATE_,OP,_FOUND)(SLIST, X, UPDATE, _i) \ + } /* end if */ \ +} /* Macro used to insert node */ -#define H5SL_INSERT(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \ - H5SL_LOCATE(INSERT, YES, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) +#define H5SL_INSERT(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \ + H5SL_LOCATE(INSERT, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) /* Macro used to remove node */ -#define H5SL_REMOVE(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \ - H5SL_LOCATE(REMOVE, YES, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) +#define H5SL_REMOVE(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \ + H5SL_LOCATE(REMOVE, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) /* Macro used to search for node */ -#define H5SL_SEARCH(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \ - H5SL_LOCATE(SEARCH, NO, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) +#define H5SL_SEARCH(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \ + H5SL_LOCATE(SEARCH, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) /* Macro used to find a node */ -#define H5SL_FIND(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \ - H5SL_LOCATE(FIND, NO, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) +#define H5SL_FIND(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \ + H5SL_LOCATE(FIND, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) /* Private typedefs & structs */ @@ -162,6 +186,7 @@ struct H5SL_node_t { const void *key; /* Pointer to node's key */ void *item; /* Pointer to node's item */ size_t level; /* The level of this node */ + uint32_t hashval; /* Hash value for key (only for strings, currently) */ struct H5SL_node_t **forward; /* Array of forward pointers from this node */ struct H5SL_node_t *backward; /* Backward pointer from this node */ }; @@ -183,7 +208,7 @@ struct H5SL_t { /* Static functions */ static size_t H5SL_random_level(int p1, size_t max_level); -static H5SL_node_t * H5SL_new_node(size_t lvl, void *item, const void *key); +static H5SL_node_t * H5SL_new_node(size_t lvl, void *item, const void *key, uint32_t hashval); static H5SL_node_t *H5SL_insert_common(H5SL_t *slist, void *item, const void *key); static herr_t H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data); static herr_t H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data); @@ -295,24 +320,25 @@ H5SL_random_level(int p1, size_t max_level) REVISION LOG --------------------------------------------------------------------------*/ static H5SL_node_t * -H5SL_new_node(size_t lvl, void *item, const void *key) +H5SL_new_node(size_t lvl, void *item, const void *key, uint32_t hashval) { H5SL_node_t *ret_value; /* New skip list node */ - FUNC_ENTER_NOAPI_NOINIT(H5SL_new_node); + FUNC_ENTER_NOAPI_NOINIT(H5SL_new_node) /* Allocate the node */ - if((ret_value=H5FL_ARR_MALLOC(H5SL_node_ptr_t,(lvl+1)))==NULL) - HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"memory allocation failed"); + if(NULL == (ret_value = H5FL_ARR_MALLOC(H5SL_node_ptr_t, (lvl + 1)))) + HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed") /* Initialize node */ - ret_value->key=key; - ret_value->item=item; - ret_value->level=lvl; - ret_value->forward=(H5SL_node_t **)((unsigned char *)ret_value+sizeof(H5SL_node_t)); + ret_value->key = key; + ret_value->item = item; + ret_value->level = lvl; + ret_value->hashval = hashval; + ret_value->forward = (H5SL_node_t **)((unsigned char *)ret_value + sizeof(H5SL_node_t)); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5SL_new_node() */ @@ -341,8 +367,8 @@ static H5SL_node_t * H5SL_insert_common(H5SL_t *slist, void *item, const void *key) { H5SL_node_t **update[H5SL_LEVEL_MAX]; /* 'update' vector */ - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ + uint32_t hashval = 0; /* Hash value for key */ size_t lvl; /* Level of new node */ int i; /* Local index value */ H5SL_node_t *ret_value; /* Return value */ @@ -364,31 +390,31 @@ H5SL_insert_common(H5SL_t *slist, void *item, const void *key) x=slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_INSERT(SCALAR, slist, x, update, i, const int, key, checked) + H5SL_INSERT(SCALAR, slist, x, update, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_INSERT(SCALAR, slist, x, update, i, const haddr_t, key, checked) + H5SL_INSERT(SCALAR, slist, x, update, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_INSERT(STRING, slist, x, update, i, char *, key, checked) + H5SL_INSERT(STRING, slist, x, update, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_INSERT(SCALAR, slist, x, update, i, const hsize_t, key, checked) + H5SL_INSERT(SCALAR, slist, x, update, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_INSERT(SCALAR, slist, x, update, i, const unsigned, key, checked) + H5SL_INSERT(SCALAR, slist, x, update, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_INSERT(SCALAR, slist, x, update, i, const size_t, key, checked) + H5SL_INSERT(SCALAR, slist, x, update, const size_t, key, -) break; case H5SL_TYPE_OBJ: - H5SL_INSERT(OBJ, slist, x, update, i, const H5_obj_t, key, checked) + H5SL_INSERT(OBJ, slist, x, update, const H5_obj_t, key, -) break; } /* end switch */ @@ -408,8 +434,8 @@ H5SL_insert_common(H5SL_t *slist, void *item, const void *key) } /* end if */ /* Create new node of proper level */ - if((x=H5SL_new_node(lvl,item,key))==NULL) - HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"can't create new skip list node"); + if(NULL == (x = H5SL_new_node(lvl, item, key, hashval))) + HGOTO_ERROR(H5E_SLIST ,H5E_NOSPACE, NULL, "can't create new skip list node") /* Update the backward links */ if(*update[0]!=NULL) { @@ -600,8 +626,8 @@ H5SL_create(H5SL_type_t type, double p, size_t max_level) new_slist->nobjs=0; /* Allocate the header node */ - if((header=H5SL_new_node(max_level-1,NULL,NULL))==NULL) - HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"memory allocation failed"); + if(NULL == (header = H5SL_new_node((max_level - 1), NULL, NULL, ULONG_MAX))) + HGOTO_ERROR(H5E_SLIST ,H5E_NOSPACE, NULL, "can't create new skip list node") /* Initialize header node's forward pointers */ for(u=0; u<max_level; u++) @@ -776,9 +802,8 @@ void * H5SL_remove(H5SL_t *slist, const void *key) { H5SL_node_t **update[H5SL_LEVEL_MAX]; /* 'update' vector */ - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ - int i; /* Local index value */ + uint32_t hashval = 0; /* Hash value for key */ void *ret_value=NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_remove); @@ -798,31 +823,31 @@ H5SL_remove(H5SL_t *slist, const void *key) x=slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_REMOVE(SCALAR, slist, x, update, i, const int, key, checked) + H5SL_REMOVE(SCALAR, slist, x, update, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_REMOVE(SCALAR, slist, x, update, i, const haddr_t, key, checked) + H5SL_REMOVE(SCALAR, slist, x, update, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_REMOVE(STRING, slist, x, update, i, char *, key, checked) + H5SL_REMOVE(STRING, slist, x, update, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_REMOVE(SCALAR, slist, x, update, i, const hsize_t, key, checked) + H5SL_REMOVE(SCALAR, slist, x, update, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_REMOVE(SCALAR, slist, x, update, i, const unsigned, key, checked) + H5SL_REMOVE(SCALAR, slist, x, update, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_REMOVE(SCALAR, slist, x, update, i, const size_t, key, checked) + H5SL_REMOVE(SCALAR, slist, x, update, const size_t, key, -) break; case H5SL_TYPE_OBJ: - H5SL_REMOVE(OBJ, slist, x, update, i, const H5_obj_t, key, checked) + H5SL_REMOVE(OBJ, slist, x, update, const H5_obj_t, key, -) break; } /* end switch */ @@ -927,9 +952,8 @@ H5SL_remove_first(H5SL_t *slist) void * H5SL_search(H5SL_t *slist, const void *key) { - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ - int i; /* Local index value */ + uint32_t hashval = 0; /* Hash value for key */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_search); @@ -949,31 +973,31 @@ H5SL_search(H5SL_t *slist, const void *key) x=slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_SEARCH(SCALAR, slist, x, -, i, const int, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_SEARCH(SCALAR, slist, x, -, i, const haddr_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_SEARCH(STRING, slist, x, -, i, char *, key, checked) + H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const hsize_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_SEARCH(SCALAR, slist, x, -, i, const unsigned, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -) break; case H5SL_TYPE_OBJ: - H5SL_SEARCH(OBJ, slist, x, -, i, const H5_obj_t, key, checked) + H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -) break; } /* end switch */ @@ -1010,9 +1034,8 @@ done: void * H5SL_less(H5SL_t *slist, const void *key) { - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ - int i; /* Local index value */ + uint32_t hashval = 0; /* Hash value for key */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_less); @@ -1032,31 +1055,31 @@ H5SL_less(H5SL_t *slist, const void *key) x=slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_SEARCH(SCALAR, slist, x, -, i, const int, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_SEARCH(SCALAR, slist, x, -, i, const haddr_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_SEARCH(STRING, slist, x, -, i, char *, key, checked) + H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const hsize_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_SEARCH(SCALAR, slist, x, -, i, const unsigned, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -) break; case H5SL_TYPE_OBJ: - H5SL_SEARCH(OBJ, slist, x, -, i, const H5_obj_t, key, checked) + H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -) break; } /* end switch */ @@ -1106,9 +1129,8 @@ done: void * H5SL_greater(H5SL_t *slist, const void *key) { - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ - int i; /* Local index value */ + uint32_t hashval = 0; /* Hash value for key */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_greater); @@ -1128,31 +1150,31 @@ H5SL_greater(H5SL_t *slist, const void *key) x = slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_SEARCH(SCALAR, slist, x, -, i, const int, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_SEARCH(SCALAR, slist, x, -, i, const haddr_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_SEARCH(STRING, slist, x, -, i, char *, key, checked) + H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const hsize_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_SEARCH(SCALAR, slist, x, -, i, const unsigned, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked) + H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -) break; case H5SL_TYPE_OBJ: - H5SL_SEARCH(OBJ, slist, x, -, i, const H5_obj_t, key, checked) + H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -) break; } /* end switch */ @@ -1192,9 +1214,8 @@ done: H5SL_node_t * H5SL_find(H5SL_t *slist, const void *key) { - H5SL_node_t *checked; /* Pointer to last node checked */ H5SL_node_t *x; /* Current node to examine */ - int i; /* Local index value */ + uint32_t hashval = 0; /* Hash value for key */ H5SL_node_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_find); @@ -1214,31 +1235,31 @@ H5SL_find(H5SL_t *slist, const void *key) x=slist->header; switch(slist->type) { case H5SL_TYPE_INT: - H5SL_FIND(SCALAR, slist, x, -, i, const int, key, checked) + H5SL_FIND(SCALAR, slist, x, -, const int, key, -) break; case H5SL_TYPE_HADDR: - H5SL_FIND(SCALAR, slist, x, -, i, const haddr_t, key, checked) + H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -) break; case H5SL_TYPE_STR: - H5SL_FIND(STRING, slist, x, -, i, char *, key, checked) + H5SL_FIND(STRING, slist, x, -, char *, key, hashval) break; case H5SL_TYPE_HSIZE: - H5SL_FIND(SCALAR, slist, x, -, i, const hsize_t, key, checked) + H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -) break; case H5SL_TYPE_UNSIGNED: - H5SL_FIND(SCALAR, slist, x, -, i, const unsigned, key, checked) + H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -) break; case H5SL_TYPE_SIZE: - H5SL_FIND(SCALAR, slist, x, -, i, const size_t, key, checked) + H5SL_FIND(SCALAR, slist, x, -, const size_t, key, -) break; case H5SL_TYPE_OBJ: - H5SL_FIND(OBJ, slist, x, -, i, const H5_obj_t, key, checked) + H5SL_FIND(OBJ, slist, x, -, const H5_obj_t, key, -) break; } /* end switch */ diff --git a/src/H5checksum.c b/src/H5checksum.c index f2e344d..e42f152 100644 --- a/src/H5checksum.c +++ b/src/H5checksum.c @@ -459,3 +459,36 @@ H5_checksum_metadata(const void *data, size_t len, uint32_t initval) FUNC_LEAVE_NOAPI(H5_checksum_lookup3(data, len, initval)) } /* end H5_checksum_metadata() */ + +/*------------------------------------------------------------------------- + * Function: H5_hash_string + * + * Purpose: Provide a simple & fast routine for hashing strings + * + * Note: This algorithm is the 'djb2' algorithm described on this page: + * http://www.cse.yorku.ca/~oz/hash.html + * + * Return: hash of input string (can't fail) + * + * Programmer: Quincey Koziol + * Tuesday, December 11, 2007 + * + *------------------------------------------------------------------------- + */ +uint32_t +H5_hash_string(const char *str) +{ + uint32_t hash = 5381; + int c; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5_hash_string) + + /* Sanity check */ + HDassert(str); + + while(c = *str++) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + FUNC_LEAVE_NOAPI(hash) +} /* end H5_hash_string() */ + diff --git a/src/H5private.h b/src/H5private.h index 3ac4da3..11f3037 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -1415,6 +1415,7 @@ H5_DLL uint32_t H5_checksum_fletcher32(const void *data, size_t len); H5_DLL uint32_t H5_checksum_crc(const void *data, size_t len); H5_DLL uint32_t H5_checksum_lookup3(const void *data, size_t len, uint32_t initval); H5_DLL uint32_t H5_checksum_metadata(const void *data, size_t len, uint32_t initval); +H5_DLL uint32_t H5_hash_string(const char *str); /* Functions for debugging */ H5_DLL herr_t H5_buffer_dump(FILE *stream, int indent, uint8_t *buf, |