summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2009-03-26 15:12:48 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2009-03-26 15:12:48 (GMT)
commit4e82abd8b3b4d96fe7bc02262c9efd316905a53e (patch)
tree3917392cfb02eef1f5096170e92caf6bd03b16b3
parentbd1fe8cd74d80f03f84ade1b0d0255222830e916 (diff)
downloadhdf5-4e82abd8b3b4d96fe7bc02262c9efd316905a53e.zip
hdf5-4e82abd8b3b4d96fe7bc02262c9efd316905a53e.tar.gz
hdf5-4e82abd8b3b4d96fe7bc02262c9efd316905a53e.tar.bz2
[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)
-rw-r--r--src/H5FDint.c21
-rw-r--r--src/H5Fsuper.c3
-rw-r--r--test/tfile.c120
3 files changed, 140 insertions, 4 deletions
diff --git a/src/H5FDint.c b/src/H5FDint.c
index aa375e2..74b3bf6 100644
--- a/src/H5FDint.c
+++ b/src/H5FDint.c
@@ -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:
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index 04abfb2..8040554 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -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. */
diff --git a/test/tfile.c b/test/tfile.c
index 2afade3..724ad4a 100644
--- a/test/tfile.c
+++ b/test/tfile.c
@@ -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
@@ -1855,6 +1857,122 @@ test_file_double_datatype_open(void)
/****************************************************************
**
+** 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);
}
+