From 4dc989f28232245dbc2f52c1330346868099234e Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Tue, 14 Aug 2007 08:33:14 -0500 Subject: [svn-r14083] Description: Correct problem with fractal heap's free space size usage gathering routine, which was "poisoning the cache" by loading an incorrectly initialized piece of metadata from the file. Tested on: FreeBSD/32 6.2 (duty) Mac OS X/32 6.2 (amazon) --- src/H5FS.c | 29 ++--------- src/H5FSprivate.h | 3 +- src/H5FSsection.c | 1 + src/H5HFpkg.h | 1 + src/H5HFspace.c | 41 ++++++++++++++++ src/H5HFstat.c | 2 +- test/fheap.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 191 insertions(+), 27 deletions(-) diff --git a/src/H5FS.c b/src/H5FS.c index e34f176..1b8ef90 100644 --- a/src/H5FS.c +++ b/src/H5FS.c @@ -167,7 +167,7 @@ H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, size_t nclasses, FUNC_ENTER_NOAPI(H5FS_open, NULL) #ifdef QAK -HDfprintf(stderr, "%s: Opening free space manager\n", FUNC); +HDfprintf(stderr, "%s: Opening free space manager, nclasses = %Zu\n", FUNC, nclasses); #endif /* QAK */ /* Check arguments. */ @@ -467,40 +467,21 @@ done: *------------------------------------------------------------------------- */ herr_t -H5FS_size(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, hsize_t *meta_size) +H5FS_size(const H5F_t *f, const H5FS_t *fspace, hsize_t *meta_size) { - H5FS_t *fspace = NULL; /* Free space header info */ - H5FS_prot_t fs_prot; /* Information for protecting free space manager */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5FS_size, FAIL) + FUNC_ENTER_NOAPI_NOFUNC(H5FS_size) /* * Check arguments. */ HDassert(f); - HDassert(H5F_addr_defined(fs_addr)); + HDassert(fspace); HDassert(meta_size); - /* Initialize user data for protecting the free space manager */ - fs_prot.nclasses = 0; - fs_prot.classes = NULL; - fs_prot.cls_init_udata = NULL; - - /* - * Load the free space header. - */ - if(NULL == (fspace = H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &fs_prot, NULL, H5AC_READ))) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "unable to load free space header") - /* Get the free space size info */ *meta_size += H5FS_HEADER_SIZE(f) + fspace->alloc_sect_size; -done: - if(fspace && H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_FSPACE, H5E_PROTECT, FAIL, "unable to release free space header") - - FUNC_LEAVE_NOAPI(ret_value) + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5FS_size() */ #ifdef H5FS_DEBUG diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h index 16f2df6..bf24b8a 100644 --- a/src/H5FSprivate.h +++ b/src/H5FSprivate.h @@ -158,8 +158,7 @@ H5_DLL H5FS_t *H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_section_class_t *classes[], void *cls_init_udata); H5_DLL H5FS_t *H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata); -H5_DLL herr_t H5FS_size(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, - hsize_t *meta_size); +H5_DLL herr_t H5FS_size(const H5F_t *f, const H5FS_t *fspace, hsize_t *meta_size); H5_DLL herr_t H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr); H5_DLL herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); diff --git a/src/H5FSsection.c b/src/H5FSsection.c index c4c30bc..505223a 100644 --- a/src/H5FSsection.c +++ b/src/H5FSsection.c @@ -1205,6 +1205,7 @@ HDfprintf(stderr, "%s: request = %Hu\n", FUNC, request); /* Check arguments. */ HDassert(fspace); + HDassert(fspace->nclasses); HDassert(request); HDassert(node); diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index 5bc1f14..461cba7 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -697,6 +697,7 @@ H5_DLL herr_t H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node, unsigned flags); H5_DLL htri_t H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, H5HF_free_section_t **node); +H5_DLL herr_t H5HF_space_size(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t *fs_size); H5_DLL herr_t H5HF_space_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node); H5_DLL herr_t H5HF_space_close(H5HF_hdr_t *hdr, hid_t dxpl_id); diff --git a/src/H5HFspace.c b/src/H5HFspace.c index 83551ba..16eae51 100644 --- a/src/H5HFspace.c +++ b/src/H5HFspace.c @@ -234,6 +234,47 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_space_size + * + * Purpose: Query the size of the heap's free space info on disk + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * August 14 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_space_size(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t *fs_size) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_space_size) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(fs_size); + + /* Check if the free space for the heap has been initialized */ + if(!hdr->fspace) + if(H5HF_space_start(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") + + /* Get free space metadata size */ + if(H5FS_size(hdr->f, hdr->fspace, fs_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't retrieve FS meta storage info") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_space_size() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_space_remove * * Purpose: Remove a section from the free space for the heap diff --git a/src/H5HFstat.c b/src/H5HFstat.c index 4971394..b2f45df 100644 --- a/src/H5HFstat.c +++ b/src/H5HFstat.c @@ -175,7 +175,7 @@ H5HF_size(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, hsize_t *heap_size) /* Get storage for free-space tracking info */ if(H5F_addr_defined(hdr->fs_addr)) - if(H5FS_size(f, dxpl_id, hdr->fs_addr, heap_size) < 0) + if(H5HF_space_size(hdr, dxpl_id, heap_size) < 0) HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't retrieve FS meta storage info") done: diff --git a/test/fheap.c b/test/fheap.c index 68ef1a5..7e82ef4 100644 --- a/test/fheap.c +++ b/test/fheap.c @@ -2744,6 +2744,146 @@ error: return(1); } /* test_filtered_create() */ + +/*------------------------------------------------------------------------- + * Function: test_size + * + * Purpose: Test querying heap size + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: Quincey Koziol + * Tuesday, August 14, 2007 + * + *------------------------------------------------------------------------- + */ +static int +test_size(hid_t fapl, H5HF_create_t *cparam) +{ + hid_t file = -1; /* File ID */ + hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */ + char filename[FHEAP_FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5HF_t *fh = NULL; /* Fractal heap wrapper */ + haddr_t fh_addr; /* Address of fractal heap */ + hsize_t empty_heap_size; /* Total size of empty heap on disk */ + hsize_t one_heap_size; /* Total size of heap on disk after inserting one object */ + hsize_t heap_size; /* Total size of heap on disk */ + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Display testing message */ + TESTING("querying heap statistics") + + + /* Create absolute heap */ + if(NULL == (fh = H5HF_create(f, dxpl, cparam))) + FAIL_STACK_ERROR + + /* Get heap's address */ + if(H5HF_get_heap_addr(fh, &fh_addr) < 0) + FAIL_STACK_ERROR + if(!H5F_addr_defined(fh_addr)) + TEST_ERROR + + /* Get an empty heap's size */ + empty_heap_size = 0; + if(H5HF_size(f, dxpl, fh_addr, &empty_heap_size) < 0) + FAIL_STACK_ERROR + if(empty_heap_size == 0) + TEST_ERROR + + /* Insert an object */ + if(add_obj(fh, dxpl, (size_t)0, (size_t)10, NULL, NULL) < 0) + TEST_ERROR + + /* Get the heap's size after inserting one object */ + one_heap_size = 0; + if(H5HF_size(f, dxpl, fh_addr, &one_heap_size) < 0) + FAIL_STACK_ERROR + if(one_heap_size <= empty_heap_size) + TEST_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, dxpl) < 0) + FAIL_STACK_ERROR + fh = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* Check the heap's size */ + heap_size = 0; + if(H5HF_size(f, dxpl, fh_addr, &heap_size) < 0) + FAIL_STACK_ERROR + if(heap_size != one_heap_size) + TEST_ERROR + + /* Re-open the heap */ + if(NULL == (fh = H5HF_open(f, H5P_DATASET_XFER_DEFAULT, fh_addr))) + FAIL_STACK_ERROR + + /* Check the heap's size */ + heap_size = 0; + if(H5HF_size(f, dxpl, fh_addr, &heap_size) < 0) + FAIL_STACK_ERROR + if(heap_size != one_heap_size) + TEST_ERROR + + /* Insert another object */ + if(add_obj(fh, dxpl, (size_t)1, (size_t)10, NULL, NULL) < 0) + TEST_ERROR + + /* Check the heap's size */ + heap_size = 0; + if(H5HF_size(f, dxpl, fh_addr, &heap_size) < 0) + FAIL_STACK_ERROR + if(heap_size != one_heap_size) + TEST_ERROR + + /* Close the fractal heap */ + if(H5HF_close(fh, H5P_DATASET_XFER_DEFAULT) < 0) + FAIL_STACK_ERROR + + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* All tests passed */ + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(fh) + H5HF_close(fh, dxpl); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_size() */ + #ifndef QAK2 /*------------------------------------------------------------------------- @@ -15622,6 +15762,7 @@ curr_test = FHEAP_TEST_NORMAL; nerrors += test_delete_open(fapl, &small_cparam, &tparam); nerrors += test_id_limits(fapl, &small_cparam); nerrors += test_filtered_create(fapl, &small_cparam); + nerrors += test_size(fapl, &small_cparam); #ifndef QAK2 #ifndef QAK -- cgit v0.12