diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2005-11-15 02:55:39 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2005-11-15 02:55:39 (GMT) |
commit | a1708eb023f2c8f8ac6c2c17bf1e598c8dff956e (patch) | |
tree | 34c87a3753b36c4c8d689d58bf456eaf261cd235 /src/H5HL.c | |
parent | bea1e576c5ef5500678f7ce913d835341b625e8f (diff) | |
download | hdf5-a1708eb023f2c8f8ac6c2c17bf1e598c8dff956e.zip hdf5-a1708eb023f2c8f8ac6c2c17bf1e598c8dff956e.tar.gz hdf5-a1708eb023f2c8f8ac6c2c17bf1e598c8dff956e.tar.bz2 |
[svn-r11712] Purpose:
New feature
Description:
Check in baseline for compact group revisions, which radically revises the
source code for managing groups and object headers.
WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
This initiates the "unstable" phase of the 1.7.x branch, leading up
to the 1.8.0 release. Please test this code, but do _NOT_ keep files created
with it - the format will change again before the release and you will not
be able to read your old files!!!
WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
Solution:
There's too many changes to really describe them all, but some of them
include:
- Stop abusing the H5G_entry_t structure and split it into two separate
structures for non-symbol table node use within the library: H5O_loc_t
for object locations in a file and H5G_name_t to store the path to
an opened object. H5G_entry_t is now only used for storing symbol
table entries on disk.
- Retire H5G_namei() in favor of a more general mechanism for traversing
group paths and issuing callbacks on objects located. This gets us out
of the business of hacking H5G_namei() for new features, generally.
- Revised H5O* routines to take a H5O_loc_t instead of H5G_entry_t
- Lots more...
Platforms tested:
h5committested and maybe another dozen configurations.... :-)
Diffstat (limited to 'src/H5HL.c')
-rw-r--r-- | src/H5HL.c | 429 |
1 files changed, 218 insertions, 211 deletions
@@ -153,8 +153,7 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/) if (NULL==(heap = H5FL_CALLOC(H5HL_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); heap->addr = *addr_p + (hsize_t)sizeof_hdr; - heap->disk_alloc = size_hint; - heap->mem_alloc = size_hint; + heap->heap_alloc = size_hint; if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + size_hint)))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); @@ -254,25 +253,24 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* heap data size */ - H5F_DECODE_LENGTH(f, p, heap->disk_alloc); - heap->mem_alloc = heap->disk_alloc; + H5F_DECODE_LENGTH(f, p, heap->heap_alloc); /* free list head */ H5F_DECODE_LENGTH(f, p, free_block); - if (free_block != H5HL_FREE_NULL && free_block >= heap->disk_alloc) + if (free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list"); /* data */ H5F_addr_decode(f, &p, &(heap->addr)); - if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + heap->mem_alloc)))) + if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + heap->heap_alloc)))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if (heap->disk_alloc && - H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->disk_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) + if (heap->heap_alloc && + H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data"); /* Build free list */ while (H5HL_FREE_NULL != free_block) { - if (free_block >= heap->disk_alloc) + if (free_block >= heap->heap_alloc) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list"); if (NULL==(fl = H5FL_MALLOC(H5HL_free_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); @@ -287,7 +285,7 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, H5F_DECODE_LENGTH(f, p, free_block); H5F_DECODE_LENGTH(f, p, fl->size); - if (fl->offset + fl->size > heap->disk_alloc) + if (fl->offset + fl->size > heap->heap_alloc) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list"); } @@ -324,7 +322,7 @@ done: * * It used to be called during cache eviction, where it * attempted to size the disk space allocation for the - * actuall size of the heap. However, this causes problems + * actual size of the heap. However, this causes problems * in the parallel case, as the reuslting disk allocations * may not be synchronized. * @@ -338,15 +336,15 @@ done: static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) { - herr_t ret_value = SUCCEED; - size_t sizeof_hdr; + size_t new_heap_size = heap->heap_alloc; /* New size of heap */ + size_t sizeof_hdr; + herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5HL_minimize_heap_space, FAIL) /* check args */ HDassert( f ); HDassert( heap ); - HDassert( heap->disk_alloc == heap->mem_alloc ); sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */ @@ -355,14 +353,14 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) * eliminating free blocks at the tail of the buffer before flushing the * buffer out. */ - if (heap->freelist) { + if(heap->freelist) { H5HL_free_t *tmp_fl; H5HL_free_t *last_fl = NULL; /* Search for a free block at the end of the buffer */ for (tmp_fl = heap->freelist; tmp_fl; tmp_fl = tmp_fl->next) /* Check if the end of this free block is at the end of the buffer */ - if (tmp_fl->offset + tmp_fl->size == heap->mem_alloc) { + if (tmp_fl->offset + tmp_fl->size == heap->heap_alloc) { last_fl = tmp_fl; break; } @@ -371,98 +369,90 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) * Found free block at the end of the buffer, decide what to do * about it */ - if (last_fl) { - size_t new_mem_size = heap->mem_alloc; /* New size of memory buffer */ - + if(last_fl) { /* * If the last free block's size is more than half the memory * buffer size (and the memory buffer is larger than the * minimum size), reduce or eliminate it. */ - if (last_fl->size >= (heap->mem_alloc / 2) && heap->mem_alloc > H5HL_MIN_HEAP) { + if(last_fl->size >= (heap->heap_alloc / 2) && heap->heap_alloc > H5HL_MIN_HEAP) { /* * Reduce size of buffer until it's too small or would * eliminate the free block */ - while (new_mem_size > H5HL_MIN_HEAP && - new_mem_size >= (last_fl->offset + H5HL_SIZEOF_FREE(f))) - new_mem_size /= 2; + while(new_heap_size > H5HL_MIN_HEAP && + new_heap_size >= (last_fl->offset + H5HL_SIZEOF_FREE(f))) + new_heap_size /= 2; /* * Check if reducing the memory buffer size would - * eliminate the free list + * eliminate the free block */ - if (new_mem_size < (last_fl->offset + H5HL_SIZEOF_FREE(f))) { + if(new_heap_size < (last_fl->offset + H5HL_SIZEOF_FREE(f))) { /* Check if this is the only block on the free list */ - if (last_fl->prev == NULL && last_fl->next == NULL) { + if(last_fl->prev == NULL && last_fl->next == NULL) { /* Double the new memory size */ - new_mem_size *= 2; + new_heap_size *= 2; /* Truncate the free block */ - last_fl->size = H5HL_ALIGN(new_mem_size - last_fl->offset); - new_mem_size = last_fl->offset + last_fl->size; + last_fl->size = H5HL_ALIGN(new_heap_size - last_fl->offset); + new_heap_size = last_fl->offset + last_fl->size; assert(last_fl->size >= H5HL_SIZEOF_FREE(f)); } else { /* * Set the size of the memory buffer to the start * of the free list */ - new_mem_size = last_fl->offset; + new_heap_size = last_fl->offset; /* Eliminate the free block from the list */ last_fl = H5HL_remove_free(heap, last_fl); - } + } /* end else */ } else { /* Truncate the free block */ - last_fl->size = H5HL_ALIGN(new_mem_size - last_fl->offset); - new_mem_size = last_fl->offset + last_fl->size; + last_fl->size = H5HL_ALIGN(new_heap_size - last_fl->offset); + new_heap_size = last_fl->offset + last_fl->size; assert(last_fl->size >= H5HL_SIZEOF_FREE(f)); assert(last_fl->size == H5HL_ALIGN(last_fl->size)); - } - - /* Resize the memory buffer and reserved space in file */ - if (new_mem_size != heap->mem_alloc) { - - heap->mem_alloc = new_mem_size; - heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + new_mem_size)); - - if (!heap->chunk) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - } - } - } - } + } /* end else */ + } /* end if */ + } /* end if */ + } /* end if */ /* * If the heap grew smaller than disk storage then move the * data segment of the heap to another contiguous block of disk * storage. */ - if (heap->mem_alloc != heap->disk_alloc) { - haddr_t old_addr = heap->addr, new_addr; + if(new_heap_size != heap->heap_alloc) { + haddr_t old_addr = heap->addr, + new_addr; + + HDassert(new_heap_size < heap->heap_alloc); - HDassert( heap->mem_alloc < heap->disk_alloc ); + /* Resize the memory buffer */ + heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + new_heap_size)); + if(!heap->chunk) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Release old space on disk */ - H5_CHECK_OVERFLOW(heap->disk_alloc, size_t, hsize_t); - H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->disk_alloc); + /* (Should be safe to free old heap space first, since it's shrinking -QAK) */ + H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); + H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc); H5E_clear_stack(NULL); /* don't really care if the free failed */ /* Allocate new space on disk */ - H5_CHECK_OVERFLOW(heap->mem_alloc, size_t, hsize_t); - - if (HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)heap->mem_alloc))) + H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t); + if(HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file space for heap") + /* Update heap info*/ heap->addr = new_addr; - - /* Set new size of block on disk */ - heap->disk_alloc = heap->mem_alloc; - } + heap->heap_alloc = new_heap_size; + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) - } /* H5HL_minimize_heap_space() */ @@ -506,7 +496,7 @@ H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf) *p++ = 0; /*reserved*/ *p++ = 0; /*reserved*/ *p++ = 0; /*reserved*/ - H5F_ENCODE_LENGTH(f, p, heap->mem_alloc); + H5F_ENCODE_LENGTH(f, p, heap->heap_alloc); H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL); H5F_addr_encode(f, &p, heap->addr); @@ -573,7 +563,6 @@ H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap) HDassert( f ); HDassert( H5F_addr_defined(addr) ); HDassert( heap ); - HDassert( heap->disk_alloc == heap->mem_alloc ); if (heap->cache_info.is_dirty) { haddr_t hdr_end_addr; @@ -588,14 +577,14 @@ H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap) if (H5F_addr_eq(heap->addr, hdr_end_addr)) { /* The header and data are contiguous */ - if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->disk_alloc), + if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc), dxpl_id, heap->chunk) < 0) HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file") } else { if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0) HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file") - if (H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->disk_alloc, + if (H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file") } @@ -717,7 +706,7 @@ H5HL_compute_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr) HDassert(heap); HDassert(size_ptr); - *size_ptr = H5HL_SIZEOF_HDR(f) + heap->disk_alloc; + *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc; FUNC_LEAVE_NOAPI(SUCCEED) } /* H5HL_compute_size() */ @@ -766,8 +755,8 @@ H5HL_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size, voi if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap"); - assert(offset < heap->mem_alloc); - assert(offset + size <= heap->mem_alloc); + assert(offset < heap->heap_alloc); + assert(offset + size <= heap->heap_alloc); if (!buf && NULL==(buf = H5MM_malloc(size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); @@ -864,7 +853,7 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_offset_into) assert(f); assert(heap); - assert(offset < heap->mem_alloc); + assert(offset < heap->heap_alloc); FUNC_LEAVE_NOAPI(heap->chunk + H5HL_SIZEOF_HDR(f) + offset) } @@ -976,12 +965,9 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * { H5HL_t *heap = NULL; unsigned heap_flags = H5AC__NO_FLAGS_SET; - H5HL_free_t *fl = NULL, *max_fl = NULL; - htri_t tri_result; - herr_t result; + H5HL_free_t *fl = NULL, *last_fl = NULL; size_t offset = 0; - size_t need_size, old_size, need_more; - size_t new_disk_alloc; + size_t need_size; hbool_t found; size_t sizeof_hdr; /* Cache H5HL header size for file */ size_t ret_value; /* Return value */ @@ -989,10 +975,10 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * FUNC_ENTER_NOAPI(H5HL_insert, (size_t)(-1)); /* check arguments */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(buf_size > 0); - assert(buf); + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(buf_size > 0); + HDassert(buf); if (0==(f->intent & H5F_ACC_RDWR)) HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, (size_t)(-1), "no write intent on file"); @@ -1016,28 +1002,28 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * * Look for a free slot large enough for this object and which would * leave zero or at least H5G_SIZEOF_FREE bytes left over. */ - for (fl=heap->freelist, found=FALSE; fl; fl=fl->next) { - if (fl->size > need_size && - fl->size - need_size >= H5HL_SIZEOF_FREE(f)) { - /* a bigger free block was found */ + for(fl = heap->freelist, found = FALSE; fl; fl = fl->next) { + if(fl->size > need_size && + fl->size - need_size >= H5HL_SIZEOF_FREE(f)) { + /* a big enough free block was found */ offset = fl->offset; fl->offset += need_size; fl->size -= need_size; - assert (fl->offset==H5HL_ALIGN (fl->offset)); - assert (fl->size==H5HL_ALIGN (fl->size)); + HDassert(fl->offset == H5HL_ALIGN(fl->offset)); + HDassert(fl->size == H5HL_ALIGN(fl->size)); found = TRUE; break; - } else if (fl->size == need_size) { + } else if(fl->size == need_size) { /* free block of exact size found */ offset = fl->offset; fl = H5HL_remove_free(heap, fl); found = TRUE; break; - } else if (!max_fl || max_fl->offset < fl->offset) { - /* use worst fit */ - max_fl = fl; + } else if(!last_fl || last_fl->offset < fl->offset) { + /* track free space that's closest to end of heap */ + last_fl = fl; } - } + } /* end for */ /* * If no free chunk was large enough, then allocate more space and @@ -1045,34 +1031,41 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * * can extend that free chunk. Otherwise we'll have to make another * free chunk. If the heap must expand, we double its size. */ - if (found==FALSE) { - need_more = MAX3(need_size, heap->mem_alloc, H5HL_SIZEOF_FREE(f)); - - new_disk_alloc = heap->disk_alloc + need_more; - HDassert( heap->disk_alloc < new_disk_alloc ); - H5_CHECK_OVERFLOW(heap->disk_alloc, size_t, hsize_t); - H5_CHECK_OVERFLOW(new_disk_alloc, size_t, hsize_t); - - /* extend the current heap if we can... */ - tri_result = H5MF_can_extend(f, H5FD_MEM_LHEAP, heap->addr, - (hsize_t)(heap->disk_alloc), - (hsize_t)need_more); - if ( tri_result == TRUE ) { - - result = H5MF_extend(f, H5FD_MEM_LHEAP, heap->addr, - (hsize_t)(heap->disk_alloc), - (hsize_t)need_more); - if ( result < 0 ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), \ - "can't extend heap on disk"); - } + if(found == FALSE) { + size_t need_more; /* How much more space we need */ + size_t new_heap_alloc; /* Final size of space allocated for heap */ + htri_t can_extend; /* Whether the local heap's data segment on disk can be extended */ + + /* At least double the heap's size, making certain there's enough room + * for the new object */ + need_more = MAX(need_size, heap->heap_alloc); + + /* If there is no last free block or it's not at the end of the heap, + * and the amount of space to allocate is not big enough to include at + * least the new object and a free-list info, trim down the amount of + * space requested to just the amount of space needed. (Generally + * speaking, this only occurs when the heap is small -QAK) + */ + if(!(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc) + && (need_more < (need_size + H5HL_SIZEOF_FREE(f)))) + need_more = need_size; - heap->disk_alloc = new_disk_alloc; + new_heap_alloc = heap->heap_alloc + need_more; + HDassert(heap->heap_alloc < new_heap_alloc); + H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); + H5_CHECK_OVERFLOW(new_heap_alloc, size_t, hsize_t); - } else { /* ...if we can't, allocate a new chunk & release the old */ + /* Check if current heap is extendible */ + can_extend = H5MF_can_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more); + if(can_extend < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to check whether heap can be extended") - haddr_t old_addr = heap->addr; + /* extend the current heap if we can... */ + if(can_extend == TRUE) { + if(H5MF_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "can't extend heap on disk") + } /* end if */ + else { /* ...if we can't, allocate a new chunk & release the old */ haddr_t new_addr; /* The new allocation may fail -- to avoid the possiblity of @@ -1081,54 +1074,50 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * */ /* allocate new disk space for the heap */ - if ( (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, - (hsize_t)new_disk_alloc)) == HADDR_UNDEF ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), \ - "unable to allocate file space for heap") - } + if((new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_alloc)) == HADDR_UNDEF) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to allocate file space for heap") /* Release old space on disk */ - H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, - (hsize_t)heap->disk_alloc); + H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc); H5E_clear_stack(NULL); /* don't really care if the free failed */ heap->addr = new_addr; - heap->disk_alloc = new_disk_alloc; - } + } /* end else */ - if (max_fl && max_fl->offset + max_fl->size == heap->mem_alloc) { + /* If the last free list in the heap is at the end of the heap, extend it */ + if(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc) { /* - * Increase the size of the maximum free block. + * Increase the size of the last free block. */ - offset = max_fl->offset; - max_fl->offset += need_size; - max_fl->size += need_more - need_size; - assert (max_fl->offset==H5HL_ALIGN (max_fl->offset)); - assert (max_fl->size==H5HL_ALIGN (max_fl->size)); + offset = last_fl->offset; + last_fl->offset += need_size; + last_fl->size += need_more - need_size; + HDassert(last_fl->offset == H5HL_ALIGN(last_fl->offset)); + HDassert(last_fl->size == H5HL_ALIGN(last_fl->size)); - if (max_fl->size < H5HL_SIZEOF_FREE(f)) { + if (last_fl->size < H5HL_SIZEOF_FREE(f)) { #ifdef H5HL_DEBUG - if (H5DEBUG(HL) && max_fl->size) { + if (H5DEBUG(HL) && last_fl->size) { fprintf(H5DEBUG(HL), "H5HL: lost %lu bytes at line %d\n", - (unsigned long)(max_fl->size), __LINE__); + (unsigned long)(last_fl->size), __LINE__); } #endif - max_fl = H5HL_remove_free(heap, max_fl); + last_fl = H5HL_remove_free(heap, last_fl); } - } else { + } /* end if */ + else { /* * Create a new free list element large enough that we can * take some space out of it right away. */ - offset = heap->mem_alloc; - if (need_more - need_size >= H5HL_SIZEOF_FREE(f)) { - if (NULL==(fl = H5FL_MALLOC(H5HL_free_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed"); - fl->offset = heap->mem_alloc + need_size; + offset = heap->heap_alloc; + if(need_more - need_size >= H5HL_SIZEOF_FREE(f)) { + if(NULL == (fl = H5FL_MALLOC(H5HL_free_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed") + fl->offset = heap->heap_alloc + need_size; fl->size = need_more - need_size; - assert (fl->offset==H5HL_ALIGN (fl->offset)); - assert (fl->size==H5HL_ALIGN (fl->size)); + HDassert(fl->offset == H5HL_ALIGN(fl->offset)); + HDassert(fl->size == H5HL_ALIGN(fl->size)); fl->prev = NULL; fl->next = heap->freelist; if (heap->freelist) heap->freelist->prev = fl; @@ -1140,40 +1129,39 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * (unsigned long)(need_more - need_size), __LINE__); #endif } - } + } /* end else */ #ifdef H5HL_DEBUG if (H5DEBUG(HL)) { fprintf(H5DEBUG(HL), "H5HL: resize mem buf from %lu to %lu bytes\n", - (unsigned long)(heap->mem_alloc), - (unsigned long)(heap->mem_alloc + need_more)); + (unsigned long)(heap->heap_alloc), + (unsigned long)(heap->heap_alloc + need_more)); } #endif - old_size = heap->mem_alloc; - heap->mem_alloc += need_more; - heap->chunk = H5FL_BLK_REALLOC(heap_chunk,heap->chunk, - (sizeof_hdr + heap->mem_alloc)); - if (NULL==heap->chunk) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed"); - - /* clear new section so junk doesn't appear in the file */ - HDmemset(heap->chunk + sizeof_hdr + old_size, 0, need_more); - } + heap->heap_alloc = new_heap_alloc; + heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc)); + if(NULL == heap->chunk) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed") + + /* Clear new section so junk doesn't appear in the file */ + /* (Avoid clearing section which will be overwritten with newly inserted data) */ + HDmemset(heap->chunk + sizeof_hdr + offset + buf_size, 0, (new_heap_alloc - (offset + buf_size))); + } /* end if */ + /* * Copy the data into the heap */ HDmemcpy(heap->chunk + sizeof_hdr + offset, buf, buf_size); /* Set return value */ - ret_value=offset; + ret_value = offset; done: - if (heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, heap_flags) != SUCCEED) - HDONE_ERROR(H5E_HEAP, H5E_PROTECT, (size_t)(-1), "unable to release object header"); - - FUNC_LEAVE_NOAPI(ret_value); + if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, heap_flags) != SUCCEED) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, (size_t)(-1), "unable to release object header") + FUNC_LEAVE_NOAPI(ret_value) } /* H5HL_insert() */ #ifdef NOT_YET @@ -1227,8 +1215,8 @@ H5HL_write(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size, co if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to load heap"); - assert(offset < heap->mem_alloc); - assert(offset + size <= heap->mem_alloc); + assert(offset < heap->heap_alloc); + assert(offset + size <= heap->heap_alloc); heap_flags |= H5AC__DIRTIED_FLAG; HDmemcpy(heap->chunk + H5HL_SIZEOF_HDR(f) + offset, buf, size); @@ -1305,9 +1293,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size) if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to load heap"); - HDassert( offset < heap->mem_alloc ); - HDassert( offset + size <= heap->mem_alloc ); - HDassert( heap->disk_alloc == heap->mem_alloc ); + HDassert( offset < heap->heap_alloc ); + HDassert( offset + size <= heap->heap_alloc ); fl = heap->freelist; heap_flags |= H5AC__DIRTIED_FLAG; @@ -1331,28 +1318,19 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size) assert (fl->offset==H5HL_ALIGN (fl->offset)); assert (fl->size==H5HL_ALIGN (fl->size)); fl2 = H5HL_remove_free(heap, fl2); - if ( ( (fl->offset + fl->size) == heap->mem_alloc ) && - ( (2 * fl->size) > heap->mem_alloc ) ) { - - if ( H5HL_minimize_heap_space(f, dxpl_id, heap) != - SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \ - "heap size minimization failed"); - } + if ( ( (fl->offset + fl->size) == heap->heap_alloc ) && + ( (2 * fl->size) > heap->heap_alloc ) ) { + if ( H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed") } HGOTO_DONE(SUCCEED); } fl2 = fl2->next; } - if ( ( (fl->offset + fl->size) == heap->mem_alloc ) && - ( (2 * fl->size) > heap->mem_alloc ) ) { - - if ( H5HL_minimize_heap_space(f, dxpl_id, heap) != SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \ - "heap size minimization failed"); - } + if ( ( (fl->offset + fl->size) == heap->heap_alloc ) && + ( (2 * fl->size) > heap->heap_alloc ) ) { + if ( H5HL_minimize_heap_space(f, dxpl_id, heap) < 0 ) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed") } HGOTO_DONE(SUCCEED); @@ -1365,28 +1343,19 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size) fl->size += fl2->size; assert (fl->size==H5HL_ALIGN (fl->size)); fl2 = H5HL_remove_free(heap, fl2); - if ( ( (fl->offset + fl->size) == heap->mem_alloc ) && - ( (2 * fl->size) > heap->mem_alloc ) ) { - - if ( H5HL_minimize_heap_space(f, dxpl_id, heap) != - SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \ - "heap size minimization failed"); - } + if ( ( (fl->offset + fl->size) == heap->heap_alloc ) && + ( (2 * fl->size) > heap->heap_alloc ) ) { + if ( H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed") } HGOTO_DONE(SUCCEED); } fl2 = fl2->next; } - if ( ( (fl->offset + fl->size) == heap->mem_alloc ) && - ( (2 * fl->size) > heap->mem_alloc ) ) { - - if ( H5HL_minimize_heap_space(f, dxpl_id, heap) != SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \ - "heap size minimization failed"); - } + if ( ( (fl->offset + fl->size) == heap->heap_alloc ) && + ( (2 * fl->size) > heap->heap_alloc ) ) { + if ( H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed") } HGOTO_DONE(SUCCEED); } @@ -1407,6 +1376,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size) #endif HGOTO_DONE(SUCCEED); } + /* * Add an entry to the free list. */ @@ -1422,14 +1392,10 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size) heap->freelist->prev = fl; heap->freelist = fl; - if ( ( (fl->offset + fl->size) == heap->mem_alloc ) && - ( (2 * fl->size) > heap->mem_alloc ) ) { - - if ( H5HL_minimize_heap_space(f, dxpl_id, heap) != SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \ - "heap size minimization failed"); - } + if ( ( (fl->offset + fl->size) == heap->heap_alloc ) && + ( (2 * fl->size) > heap->heap_alloc ) ) { + if ( H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed") } done: @@ -1488,8 +1454,8 @@ H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) assert(!H5F_addr_overflow(addr,sizeof_hdr)); if(H5F_addr_eq(heap->addr,addr+sizeof_hdr)) { /* Free the contiguous local heap in one call */ - H5_CHECK_OVERFLOW(sizeof_hdr+heap->disk_alloc,size_t,hsize_t); - if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)(sizeof_hdr+heap->disk_alloc))<0) + H5_CHECK_OVERFLOW(sizeof_hdr+heap->heap_alloc,size_t,hsize_t); + if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)(sizeof_hdr+heap->heap_alloc))<0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap"); } /* end if */ else { @@ -1499,8 +1465,8 @@ H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header"); /* Free the local heap's data */ - H5_CHECK_OVERFLOW(heap->disk_alloc,size_t,hsize_t); - if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->disk_alloc)<0) + H5_CHECK_OVERFLOW(heap->heap_alloc,size_t,hsize_t); + if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc)<0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data"); } /* end else */ @@ -1518,3 +1484,44 @@ done: FUNC_LEAVE_NOAPI(ret_value); } /* end H5HL_delete() */ + +/*------------------------------------------------------------------------- + * Function: H5HL_get_size + * + * Purpose: Retrieves the current size of a heap + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Nov 7 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size) +{ + H5HL_t *heap = NULL; /* Heap to query */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5HL_get_size, FAIL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(size); + + /* Get heap pointer */ + if(NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") + + /* Set the size to return */ + *size = heap->heap_alloc; + +done: + if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_get_size() */ + |