summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Laird <jlaird@hdfgroup.org>2007-01-04 16:39:39 (GMT)
committerJames Laird <jlaird@hdfgroup.org>2007-01-04 16:39:39 (GMT)
commit75121771bbd468e333419a65511164a1099668a4 (patch)
tree3cad2efbdca3d0677ff18117f79367dbe2937360
parent5b16810ac29d497c8cc6e28f23031b34a6d44a53 (diff)
downloadhdf5-75121771bbd468e333419a65511164a1099668a4.zip
hdf5-75121771bbd468e333419a65511164a1099668a4.tar.gz
hdf5-75121771bbd468e333419a65511164a1099668a4.tar.bz2
[svn-r13107] Fixed shared message indexes to clean themselves up when they're deleted.
Creating shared messages and then deleting them should return the file to its original state. Added a test for this. Tested on Windows, smirom, and kagiso.
-rwxr-xr-xsrc/H5SM.c56
-rw-r--r--test/tsohm.c162
2 files changed, 213 insertions, 5 deletions
diff --git a/src/H5SM.c b/src/H5SM.c
index 65d2392..9f93bd4 100755
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -427,7 +427,7 @@ H5SM_create_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id)
HDassert(header);
HDassert(header->index_addr == HADDR_UNDEF);
- HDassert(header->btree_to_list <= header->list_to_btree);
+ HDassert(header->btree_to_list <= header->list_to_btree + 1);
/* In most cases, the index starts as a list */
if(header->list_to_btree > 0)
@@ -812,6 +812,12 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header,
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index")
list = NULL;
+ /* JAMES: same as list deletion in try_delete? */
+ /* Remove the list from the cache */
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove list index from cache")
+
+ /* Free the list's space on disk */
list_size = H5SM_LIST_SIZE(f, header->list_to_btree);
if(H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, dxpl_id, header->index_addr, list_size) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to free shared message list")
@@ -1147,13 +1153,53 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header,
--header->num_messages;
*cache_flags |= H5AC__DIRTIED_FLAG;
- /* If we've just passed the btree-to-list cutoff, convert this B-tree
- * into a list
+ /* If there are no messages left in the index, delete it
+ * JAMES: make this a separate function
*/
- /* JAMES: there's an off-by-one error here */
+ if(header->num_messages <=0) {
+
+ if(header->index_type == H5SM_LIST) {
+ hsize_t list_size; /* Size of list on disk */
+
+ /* Remove the list from the cache */
+ HDassert(list);
+ if(H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index")
+ list = NULL;
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove list index from cache")
+
+ /* Free the file space used */
+ list_size = H5SM_LIST_SIZE(f, header->list_to_btree);
+ if(H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, dxpl_id, header->index_addr, list_size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to free shared message list")
+
+ } else {
+ HDassert(header->index_type == H5SM_BTREE);
+
+ if(H5B2_delete(f, dxpl_id, H5SM_INDEX, header->index_addr, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to delete B-tree")
+ }
+
+ /* Free the fractal heap */
+ /* Release the fractal heap if we opened it */
+ HDassert(fheap);
+ if(H5HF_close(fheap, dxpl_id) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
+ fheap = NULL;
+ if(H5HF_delete(f, dxpl_id, header->heap_addr) < 0)
+ HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete fractal heap")
+
+ header->index_addr = HADDR_UNDEF;
+ header->heap_addr = HADDR_UNDEF;
+
+ } else if(header->index_type == H5SM_BTREE && header->num_messages < header->btree_to_list)
+ /* JAMES: there's an off-by-one error here? */
/* JAMES: make this a separate function */
- if(header->index_type == H5SM_BTREE && header->num_messages < header->btree_to_list)
{
+ /* Otherwise, if we've just passed the btree-to-list cutoff, convert
+ * this B-tree into a list
+ */
/* Remember the btree address for this index; we'll overwrite the
* address in the index header
*/
diff --git a/test/tsohm.c b/test/tsohm.c
index 553a0af..e38cbbd 100644
--- a/test/tsohm.c
+++ b/test/tsohm.c
@@ -2769,6 +2769,166 @@ static void test_sohm_delete()
}
+
+/*-------------------------------------------------------------------------
+ * Function: test_sohm_delete_revert_helper
+ *
+ * Purpose: Tests that shared object header message deletion returns
+ * the file to its previous state using the supplied FCPL.
+ *
+ * Creates shared messages and then deletes them. Ensures
+ * that the file has not grown in size.
+ *
+ * Programmer: James Laird
+ * Wednesday, January 3, 2007
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void test_sohm_delete_revert_helper(hid_t fcpl_id)
+{
+ hid_t file_id;
+ hid_t dspace_id;
+ hid_t dset_id;
+ hsize_t dims[1] = {1};
+ h5_stat_size_t initial_filesize, deleted_filesize;
+ herr_t ret;
+
+ /* Create a dataspace for later */
+ dspace_id = H5Screate_simple(1, dims, dims);
+ CHECK_I(dspace_id, "H5Screate_simple");
+
+ /* Create a file using the FCPL supplied*/
+ file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fcreate");
+
+ /* Close the file and get its size */
+ ret = H5Fclose(file_id);
+ CHECK_I(ret, "H5Fclose");
+ initial_filesize = h5_get_file_size(FILENAME);
+
+
+ /* Re-create the file and create a dataset in it */
+ file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fcreate");
+
+ dset_id = H5Dcreate(file_id, "dset", H5T_NATIVE_SHORT, dspace_id, H5P_DEFAULT);
+ CHECK_I(dset_id, "H5Dcreate");
+
+ /* Close the dataset and delete it */
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+ ret = H5Ldelete(file_id, "dset", H5P_DEFAULT);
+ CHECK_I(ret, "H5Ldelete");
+
+ /* Close the file and get its size */
+ ret = H5Fclose(file_id);
+ CHECK_I(ret, "H5Fclose");
+ deleted_filesize = h5_get_file_size(FILENAME);
+
+ VERIFY(deleted_filesize, initial_filesize, "h5_get_file_size");
+
+
+ /* Repeat, creating two datasets in the file */
+ file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fcreate");
+
+ /* Create and close the first dataset */
+ dset_id = H5Dcreate(file_id, "dset", H5T_NATIVE_SHORT, dspace_id, H5P_DEFAULT);
+ CHECK_I(dset_id, "H5Dcreate");
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+
+ /* Create and close the second. These messages should be shared */
+ dset_id = H5Dcreate(file_id, "dset2", H5T_NATIVE_SHORT, dspace_id, H5P_DEFAULT);
+ CHECK_I(dset_id, "H5Dcreate");
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+
+ /* Delete both datasets */
+ ret = H5Ldelete(file_id, "dset", H5P_DEFAULT);
+ CHECK_I(ret, "H5Ldelete");
+ ret = H5Ldelete(file_id, "dset2", H5P_DEFAULT);
+ CHECK_I(ret, "H5Ldelete");
+
+ /* Close the file and get its size */
+ ret = H5Fclose(file_id);
+ CHECK_I(ret, "H5Fclose");
+ deleted_filesize = h5_get_file_size(FILENAME);
+
+ VERIFY(deleted_filesize, initial_filesize, "h5_get_file_size");
+
+
+ /* Cleanup */
+ ret = H5Sclose(dspace_id);
+ CHECK_I(ret, "H5Sclose");
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_sohm_delete_revert
+ *
+ * Purpose: Calls test_sohm_delete_revert_helper with different FCPLs.
+ *
+ * Programmer: James Laird
+ * Wednesday, January 3, 2007
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void test_sohm_delete_revert()
+{
+ hid_t fcpl_id;
+ herr_t ret;
+
+ /* Create an fcpl with messages in two indexes */
+ fcpl_id = H5Pcreate(H5P_FILE_CREATE);
+ CHECK_I(fcpl_id, "H5Pcreate");
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_DTYPE_FLAG, 10);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_SDSPACE_FLAG, 10);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+
+ /* Call the helper function to test this FCPL. */
+ test_sohm_delete_revert_helper(fcpl_id);
+
+ /* Try using B-trees */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+ test_sohm_delete_revert_helper(fcpl_id);
+
+
+ /* Try sharing all messages */
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_ALL_FLAG, 10);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, 5);
+
+ test_sohm_delete_revert_helper(fcpl_id);
+
+ /* Try using B-trees */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+ test_sohm_delete_revert_helper(fcpl_id);
+
+ /* There should be at least two messages in the test (datatype and
+ * dataspace). Use an index that will transition from a list to
+ * a B-tree and back.
+ */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+ test_sohm_delete_revert_helper(fcpl_id);
+
+ ret = H5Pclose(fcpl_id);
+ CHECK_I(ret, "H5Pclose");
+}
+
+
/*-------------------------------------------------------------------------
* Function: test_sohm_extlink_helper
*
@@ -2891,6 +3051,8 @@ test_sohm(void)
* SOHMs, closing and reopening file after
* each write. */
test_sohm_delete(); /* Test deleting shared messages */
+ test_sohm_delete_revert(); /* Test that a file with SOHMs becomes an
+ * empty file again when they are deleted. */
test_sohm_extlink(); /* Test SOHMs when external links are used */
} /* test_sohm() */