From 75121771bbd468e333419a65511164a1099668a4 Mon Sep 17 00:00:00 2001 From: James Laird Date: Thu, 4 Jan 2007 11:39:39 -0500 Subject: [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. --- src/H5SM.c | 56 +++++++++++++++++++-- test/tsohm.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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() */ -- cgit v0.12