[svn-r16615] Purpose: Fix bug 1499

Description:
Due to a bug in H5F_super_read, every time a file with a user block was opened
it would grow by the size of the user block.  The bug has been fixed, and
comments have been added to clarify when an eoa address should be relative and
when it should be absolute.

Tested:
jam, linew (h5committest)
This commit is contained in:
Neil Fortner 2009-03-26 10:12:48 -05:00
parent bd1fe8cd74
commit 4e82abd8b3
3 changed files with 140 additions and 4 deletions

View File

@ -194,6 +194,11 @@ done:
*
* Purpose: Private version of H5FDset_eoa()
*
* This function expects the EOA is a RELATIVE address, i.e.
* relative to the base address. This is NOT the same as the
* EOA stored in the superblock, which is an absolute
* address. Object addresses are relative.
*
* Return: Success: Non-negative
* Failure: Negative, no side effect
*
@ -212,7 +217,7 @@ H5FD_set_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr)
HDassert(file && file->cls);
HDassert(H5F_addr_defined(addr) && addr <= file->maxaddr);
/* Dispatch to driver */
/* Dispatch to driver, convert to absolute address */
if((file->cls->set_eoa)(file, type, addr + file->base_addr) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver set_eoa request failed")
@ -226,6 +231,11 @@ done:
*
* Purpose: Private version of H5FDget_eoa()
*
* This function returns the EOA as a RELATIVE address, i.e.
* relative to the base address. This is NOT the same as the
* EOA stored in the superblock, which is an absolute
* address. Object addresses are relative.
*
* Return: Success: First byte after allocated memory.
* Failure: HADDR_UNDEF
*
@ -247,7 +257,7 @@ H5FD_get_eoa(const H5FD_t *file, H5FD_mem_t type)
if(HADDR_UNDEF == (ret_value = (file->cls->get_eoa)(file, type)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
/* Adjust for base address in file */
/* Adjust for base address in file (convert to relative address) */
ret_value -= file->base_addr;
done:
@ -260,6 +270,11 @@ done:
*
* Purpose: Private version of H5FDget_eof()
*
* This function returns the EOF as a RELATIVE address, i.e.
* relative to the base address. This will be different
* from the end of the physical file if there is a user
* block.
*
* Return: Success: The EOF address.
*
* Failure: HADDR_UNDEF
@ -288,7 +303,7 @@ H5FD_get_eof(const H5FD_t *file)
else
ret_value = file->maxaddr;
/* Adjust for base address in file */
/* Adjust for base address in file (convert to relative address) */
ret_value -= file->base_addr;
done:

View File

@ -560,7 +560,8 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
* Tell the file driver how much address space has already been
* allocated so that it knows how to allocate additional memory.
*/
if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, stored_eoa) < 0)
/* (Account for the stored EOA being absolute offset -NAF) */
if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, stored_eoa - H5F_BASE_ADDR(f)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to set end-of-address marker for file")
/* Read the file's superblock extension, if there is one. */

View File

@ -79,6 +79,8 @@
#define TESTA_NX 4
#define TESTA_NY 5
#define USERBLOCK_SIZE ((hsize_t) 512)
static void
create_objects(hid_t, hid_t, hid_t *, hid_t *, hid_t *, hid_t *);
static void
@ -1853,6 +1855,122 @@ test_file_double_datatype_open(void)
CHECK(ret, FAIL, "H5Fclose");
} /* end test_file_double_dataset_open() */
/****************************************************************
**
** test_userblock_file_size(): low-level file test routine.
** This test checks that the presence of a userblock
** affects the file size in the expected manner, and that
** the filesize is not changed by reopening the file. It
** creates two files which are identical except that one
** contains a userblock, and verifies that their file sizes
** differ exactly by the userblock size.
**
*****************************************************************/
static void
test_userblock_file_size(void)
{
hid_t file1_id, file2_id;
hid_t group1_id, group2_id;
hid_t dset1_id, dset2_id;
hid_t space_id;
hid_t fcpl2_id;
hsize_t dims[2] = {3, 4};
hsize_t filesize1, filesize2, filesize;
herr_t ret; /* Generic return value */
/* Output message about test being performed */
MESSAGE(5, ("Testing file size with user block\n"));
/* Create property list with userblock size set */
fcpl2_id = H5Pcreate(H5P_FILE_CREATE);
CHECK(fcpl2_id, FAIL, "H5Pcreate");
ret = H5Pset_userblock(fcpl2_id, USERBLOCK_SIZE);
CHECK(ret, FAIL, "H5Pset_userblock");
/* Create files. Onyl file2 with have a userblock. */
file1_id = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
CHECK(file1_id, FAIL, "H5Fcreate");
file2_id = H5Fcreate(FILE2, H5F_ACC_TRUNC, fcpl2_id, H5P_DEFAULT);
CHECK(file2_id, FAIL, "H5Fcreate");
/* Create groups */
group1_id = H5Gcreate2(file1_id, GROUP1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
CHECK(group1_id, FAIL, "H5Gcreate2");
group2_id = H5Gcreate2(file2_id, GROUP1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
CHECK(group2_id, FAIL, "H5Gcreate2");
/* Create dataspace */
space_id = H5Screate_simple(2, dims, NULL);
CHECK(space_id, FAIL, "H5Screate_simple");
/* Create datasets */
dset1_id = H5Dcreate2(file1_id, DSET2, H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
CHECK(dset1_id, FAIL, "H5Dcreate2");
dset2_id = H5Dcreate2(file2_id, DSET2, H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
CHECK(dset2_id, FAIL, "H5Dcreate2");
/* Close IDs */
ret = H5Dclose(dset1_id);
CHECK(ret, FAIL, "H5Dclose");
ret = H5Dclose(dset2_id);
CHECK(ret, FAIL, "H5Dclose");
ret = H5Sclose(space_id);
CHECK(ret, FAIL, "H5Sclose");
ret = H5Gclose(group1_id);
CHECK(ret, FAIL, "H5Gclose");
ret = H5Gclose(group2_id);
CHECK(ret, FAIL, "H5Gclose");
ret = H5Pclose(fcpl2_id);
CHECK(ret, FAIL, "H5Pclose");
/* Close files */
ret = H5Fclose(file1_id);
CHECK(ret, FAIL, "H5Fclose");
ret = H5Fclose(file2_id);
CHECK(ret, FAIL, "H5Fclose");
/* Reopen files */
file1_id = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
CHECK(ret, FAIL, "H5Fopen");
file2_id = H5Fopen(FILE2, H5F_ACC_RDWR, H5P_DEFAULT);
CHECK(ret, FAIL, "H5Fopen");
/* Check file sizes */
ret = H5Fget_filesize(file1_id, &filesize1);
CHECK(ret, FAIL, "H5Fget_filesize");
ret = H5Fget_filesize(file2_id, &filesize2);
CHECK(ret, FAIL, "H5Fget_filesize");
/* Verify that the file sizes differ exactly by the userblock size */
VERIFY(filesize2, filesize1 + USERBLOCK_SIZE, "H5Fget_filesize");
/* Close files */
ret = H5Fclose(file1_id);
CHECK(ret, FAIL, "H5Fclose");
ret = H5Fclose(file2_id);
CHECK(ret, FAIL, "H5Fclose");
/* Reopen files */
file1_id = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
CHECK(ret, FAIL, "H5Fopen");
file2_id = H5Fopen(FILE2, H5F_ACC_RDWR, H5P_DEFAULT);
CHECK(ret, FAIL, "H5Fopen");
/* Verify file sizes did not change */
ret = H5Fget_filesize(file1_id, &filesize);
CHECK(ret, FAIL, "H5Fget_filesize");
VERIFY(filesize, filesize1, "H5Fget_filesize");
ret = H5Fget_filesize(file2_id, &filesize);
CHECK(ret, FAIL, "H5Fget_filesize");
VERIFY(filesize, filesize2, "H5Fget_filesize");
/* Close files */
ret = H5Fclose(file1_id);
CHECK(ret, FAIL, "H5Fclose");
ret = H5Fclose(file2_id);
CHECK(ret, FAIL, "H5Fclose");
} /* end test_userblock_file_size() */
/****************************************************************
**
** test_file(): Main low-level file I/O test routine.
@ -1884,6 +2002,7 @@ test_file(void)
test_file_double_dataset_open(); /* Test opening same dataset from two files works properly */
test_file_double_datatype_open(); /* Test opening same named datatype from two files works properly */
#endif /*H5_CANNOT_OPEN_TWICE*/
test_userblock_file_size(); /* Tests that files created with a userblock have the correct size */
} /* test_file() */
@ -1909,3 +2028,4 @@ cleanup_file(void)
HDremove(FILE3);
HDremove(FILE4);
}