summaryrefslogtreecommitdiffstats
path: root/src/H5O.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/H5O.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/H5O.c')
-rw-r--r--src/H5O.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/src/H5O.c b/src/H5O.c
index f1b4a23..0ee7706 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -75,7 +75,7 @@ static herr_t H5O_remove_real(H5G_entry_t *ent, const H5O_class_t *type,
int sequence, hid_t dxpl_id);
static unsigned H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type,
size_t size);
-static unsigned H5O_alloc_extend_chunk(H5O_t *oh, unsigned chunkno, size_t size);
+static unsigned H5O_alloc_extend_chunk(H5F_t *f, H5O_t *oh, unsigned chunkno, size_t size);
static unsigned H5O_alloc_new_chunk(H5F_t *f, H5O_t *oh, size_t size);
static herr_t H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
static herr_t H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg);
@@ -715,7 +715,11 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh)
assert(cont->chunkno < oh->nchunks);
assert(!H5F_addr_defined(oh->chunk[cont->chunkno].addr));
cont->size = oh->chunk[cont->chunkno].size;
- if (HADDR_UNDEF==(cont->addr=H5MF_alloc(f,
+
+ /* Free the space we'd reserved in the file to hold this chunk */
+ H5MF_free_reserved(f, cont->size);
+
+ if (HADDR_UNDEF==(cont->addr=H5MF_alloc(f,
H5FD_MEM_OHDR, dxpl_id, (hsize_t)cont->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate space for object header data");
oh->chunk[cont->chunkno].addr = cont->addr;
@@ -2592,6 +2596,10 @@ done:
* that message will be extended with the chunk. Otherwise a
* new null message is created.
*
+ * F is the file in which the chunk will be written. It is
+ * included to ensure that there is enough space to extend
+ * this chunk.
+ *
* Return: Success: Message index for null message which
* is large enough to hold SIZE bytes.
*
@@ -2610,7 +2618,7 @@ done:
*-------------------------------------------------------------------------
*/
static unsigned
-H5O_alloc_extend_chunk(H5O_t *oh, unsigned chunkno, size_t size)
+H5O_alloc_extend_chunk(H5F_t *f, H5O_t *oh, unsigned chunkno, size_t size)
{
unsigned u;
unsigned idx;
@@ -2638,6 +2646,11 @@ H5O_alloc_extend_chunk(H5O_t *oh, unsigned chunkno, size_t size)
delta = MAX (H5O_MIN_SIZE, aligned_size - oh->mesg[idx].raw_size);
assert (delta=H5O_ALIGN (delta));
+
+ /* Reserve space in the file to hold the increased chunk size */
+ if( H5MF_reserve(f, delta) < 0 )
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "unable to reserve space in file");
+
oh->mesg[idx].dirty = TRUE;
oh->mesg[idx].raw_size += delta;
@@ -2665,6 +2678,13 @@ H5O_alloc_extend_chunk(H5O_t *oh, unsigned chunkno, size_t size)
} /* end if */
}
+ /* Reserve space in the file */
+ delta = MAX(H5O_MIN_SIZE, aligned_size+H5O_SIZEOF_MSGHDR(f));
+ delta = H5O_ALIGN(delta);
+
+ if( H5MF_reserve(f, delta) < 0 )
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "unable to reserve space in file");
+
/* create a new null message */
if (oh->nmesgs >= oh->alloc_nmesgs) {
unsigned na = oh->alloc_nmesgs + H5O_NMESGS;
@@ -2675,8 +2695,6 @@ H5O_alloc_extend_chunk(H5O_t *oh, unsigned chunkno, size_t size)
oh->alloc_nmesgs = na;
oh->mesg = x;
}
- delta = MAX(H5O_MIN_SIZE, aligned_size+H5O_SIZEOF_MSGHDR(f));
- delta = H5O_ALIGN(delta);
idx = oh->nmesgs++;
oh->mesg[idx].type = H5O_NULL;
oh->mesg[idx].dirty = TRUE;
@@ -2805,6 +2823,10 @@ H5O_alloc_new_chunk(H5F_t *f, H5O_t *oh, size_t size)
size = MAX(H5O_MIN_SIZE, size + H5O_SIZEOF_MSGHDR(f));
assert (size == H5O_ALIGN (size));
+ /* Reserve space in the file to hold the new chunk */
+ if( H5MF_reserve(f, size) < 0 )
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "unable to reserve space in file for new chunk");
+
/*
* Create the new chunk without giving it a file address.
*/
@@ -2969,7 +2991,7 @@ H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size)
* since we can just increase the size of that chunk.
*/
for (chunkno = 0; chunkno < oh->nchunks; chunkno++) {
- if ((idx = H5O_alloc_extend_chunk(oh, chunkno, size)) != UFAIL) {
+ if ((idx = H5O_alloc_extend_chunk(f, oh, chunkno, size)) != UFAIL) {
break;
}
H5E_clear(NULL);