summaryrefslogtreecommitdiffstats
path: root/src/H5HL.c
diff options
context:
space:
mode:
authorJames Laird <jlaird@hdfgroup.org>2004-07-14 19:34:24 (GMT)
committerJames Laird <jlaird@hdfgroup.org>2004-07-14 19:34:24 (GMT)
commita0c466cd99e6d62725ac1828755b042c2dcb6c85 (patch)
tree8ef8956600e8765fe9a0fc96dcb5faa0798032e8 /src/H5HL.c
parent769ee96c1fd7cdcc4de2f2b1f36e943ebf9fff8b (diff)
downloadhdf5-a0c466cd99e6d62725ac1828755b042c2dcb6c85.zip
hdf5-a0c466cd99e6d62725ac1828755b042c2dcb6c85.tar.gz
hdf5-a0c466cd99e6d62725ac1828755b042c2dcb6c85.tar.bz2
[svn-r8877]
Purpose: Bug Fix Description: If an HDF5 file grows larger than its address space, it dies and is unable to write any data. This is more likely to happen since users are able to change the number of bytes used to store addresses in the file. Solution: HDF5 now throws an error instead of dying. In addition, it "reserves" address space for the local heap and for object headers (which do not allocate space immediately). This ensures that after the error occurs, there is enough address space left to flush the entire file to disk, so no data is lost. A more complete explanation is at /doc/html/TechNotes/ReservedFileSpace.html Platforms tested: sleipnir, copper (parallel), verbena, arabica, Windows (Visual Studio 7) Solution: Platforms tested: Misc. update:
Diffstat (limited to 'src/H5HL.c')
-rw-r--r--src/H5HL.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/src/H5HL.c b/src/H5HL.c
index bf402b0..bfbb2ac 100644
--- a/src/H5HL.c
+++ b/src/H5HL.c
@@ -155,6 +155,7 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/)
heap->addr = *addr_p + (hsize_t)sizeof_hdr;
heap->disk_alloc = size_hint;
heap->mem_alloc = size_hint;
+ heap->disk_resrv = 0;
if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + size_hint))))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
@@ -253,7 +254,7 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
/* Allocate space in memory for the heap */
if (NULL==(heap = H5FL_CALLOC(H5HL_t)))
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;
@@ -337,6 +338,13 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */
/*
+ * When the heap is being flushed to disk, release the file space reserved
+ * for it.
+ */
+ H5MF_free_reserved(f, heap->disk_resrv);
+ heap->disk_resrv = 0;
+
+ /*
* Check to see if we can reduce the size of the heap in memory by
* eliminating free blocks at the tail of the buffer before flushing the
* buffer out.
@@ -406,8 +414,9 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
assert(last_fl->size == H5HL_ALIGN(last_fl->size));
}
- /* Resize the memory buffer */
+ /* 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));
@@ -939,6 +948,7 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void *
size_t offset = 0;
size_t need_size, old_size, need_more;
hbool_t found;
+ size_t disk_resrv; /* Amount of additional space to reserve in file */
size_t sizeof_hdr; /* Cache H5HL header size for file */
size_t ret_value; /* Return value */
@@ -1004,6 +1014,19 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void *
if (found==FALSE) {
need_more = MAX3(need_size, heap->mem_alloc, H5HL_SIZEOF_FREE(f));
+ /* Reserve space in the file to hold the increased heap size
+ */
+ if( heap->disk_resrv == heap->mem_alloc)
+ disk_resrv = need_more;
+ else
+ disk_resrv = heap->mem_alloc + need_more - heap->disk_resrv;
+
+ if( H5MF_reserve(f, disk_resrv) < 0 )
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to reserve space in file");
+
+ /* Update heap's record of how much space it has reserved */
+ heap->disk_resrv += disk_resrv;
+
if (max_fl && max_fl->offset + max_fl->size == heap->mem_alloc) {
/*
* Increase the size of the maximum free block.