diff options
Diffstat (limited to 'test/mf.c')
-rw-r--r-- | test/mf.c | 8995 |
1 files changed, 8995 insertions, 0 deletions
diff --git a/test/mf.c b/test/mf.c new file mode 100644 index 0000000..3197989 --- /dev/null +++ b/test/mf.c @@ -0,0 +1,8995 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Tests for file memory management consist of 3 parts: + * test_mf_eoa_*() tests for file meomory that interact with file allocation + * test_mf_fs_*() tests for file memory that interact with the free-space manager + * test_mf_aggr_*() tests for file memory that interact with the aggregators + * test_mf_align_*() tests for file memory with alignment setting + * test_filespace_*() tests for file space management + * test_page_*() tests for file space paging + */ + +#include "h5test.h" + +#define H5MF_FRIEND /*suppress error about including H5MFpkg */ +#include "H5MFpkg.h" + +#define H5FS_FRIEND /*suppress error about including H5FSpkg */ +#include "H5FSpkg.h" + +#define H5F_FRIEND /*suppress error about including H5Fpkg */ +#define H5F_TESTING +#include "H5Fpkg.h" + +#include "H5FLprivate.h" +#include "H5Iprivate.h" +#include "H5VMprivate.h" + +#define FILENAME_LEN 1024 + +#define TBLOCK_SIZE1 1 +#define TBLOCK_SIZE2 2 +#define TBLOCK_SIZE3 3 +#define TBLOCK_SIZE4 4 +#define TBLOCK_SIZE5 5 +#define TBLOCK_SIZE6 6 +#define TBLOCK_SIZE7 7 +#define TBLOCK_SIZE8 8 +#define TBLOCK_SIZE10 10 +#define TBLOCK_SIZE11 11 +#define TBLOCK_SIZE20 20 +#define TBLOCK_SIZE30 30 +#define TBLOCK_SIZE36 36 +#define TBLOCK_SIZE40 40 +#define TBLOCK_SIZE50 50 +#define TBLOCK_SIZE80 80 +#define TBLOCK_SIZE90 90 +#define TBLOCK_SIZE98 98 +#define TBLOCK_SIZE100 100 +#define TBLOCK_SIZE150 150 +#define TBLOCK_SIZE200 200 +#define TBLOCK_SIZE600 600 +#define TBLOCK_SIZE700 700 +#define TBLOCK_SIZE1034 1034 +#define TBLOCK_SIZE1970 1970 +#define TBLOCK_SIZE2048 2048 +#define TBLOCK_SIZE2058 2058 +#define TBLOCK_SIZE2192 2192 +#define TBLOCK_SIZE3080 3080 +#define TBLOCK_SIZE3088 3088 +#define TBLOCK_SIZE3198 3198 +#define TBLOCK_SIZE3286 3286 +#define TBLOCK_SIZE3248 3248 +#define TBLOCK_SIZE3900 3900 +#define TBLOCK_SIZE4020 4020 +#define TBLOCK_SIZE4086 4086 +#define TBLOCK_SIZE4096 4096 +#define TBLOCK_SIZE4106 4106 +#define TBLOCK_SIZE5000 5000 +#define TBLOCK_SIZE6000 6000 +#define TBLOCK_SIZE8000 8000 +#define TBLOCK_SIZE8100 8100 +#define TBLOCK_SIZE8192 8192 +#define TBLOCK_SIZE8190 8190 +#define TBLOCK_SIZE12000 12000 + +#define TBLOCK_ADDR70 70 +#define TBLOCK_ADDR100 100 + +#define TEST_ALIGN16 16 +#define TEST_ALIGN1024 1024 +#define TEST_ALIGN4096 4096 + +#define TEST_THRESHOLD10 10 +#define TEST_THRESHOLD3 3 + +const char *FILENAME[] = { + "mf", + NULL +}; + +typedef enum { + TEST_NORMAL, /* size of aggregator is >= alignment size */ + TEST_AGGR_SMALL, /* size of aggregator is smaller than alignment size */ + TEST_NTESTS /* The number of test types, must be last */ +} test_type_t; + +static int check_stats(const H5F_t *f, const H5FS_t *frsp, H5FS_stat_t *state); + +static unsigned test_mf_eoa(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_eoa_shrink(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_eoa_extend(const char *env_h5_drvr, hid_t fapl); +static unsigned test_dichotomy(hid_t fapl); +static unsigned test_mf_fs_start(hid_t fapl); +static unsigned test_mf_fs_alloc_free(hid_t fapl); +static unsigned test_mf_fs_extend(hid_t fapl); +static unsigned test_mf_fs_absorb(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_aggr_alloc1(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_aggr_alloc2(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_aggr_alloc3(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_aggr_alloc4(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_aggr_alloc5(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_aggr_alloc6(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_aggr_alloc7(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_aggr_extend(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_aggr_absorb(const char *env_h5_drvr, hid_t fapl); +static unsigned test_mf_align_eoa(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl); +static unsigned test_mf_align_fs(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl); +static unsigned test_mf_align_alloc1(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl); +static unsigned test_mf_align_alloc2(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl); +static unsigned test_mf_align_alloc3(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl); +static unsigned test_mf_align_alloc4(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl); +static unsigned test_mf_align_alloc5(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl); +static unsigned test_mf_align_alloc6(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl); +static unsigned test_mf_tmp(const char *env_h5_drvr, hid_t fapl, hbool_t new_format); +static unsigned test_mf_fs_gone(const char *env_h5_drvr, hid_t fapl, hbool_t new_format); +static unsigned test_mf_strat_thres_gone(const char *env_h5_drvr, hid_t fapl, hbool_t new_format); +static unsigned test_mf_fs_persist(const char *env_h5_drvr, hid_t fapl, hbool_t new_format); +static unsigned test_mf_strat_thres_persist(const char *env_h5_drvr, hid_t fapl, hbool_t new_format); +static unsigned test_mf_fs_persist_split(void); +static unsigned test_mf_fs_persist_multi(void); +static unsigned test_page_alloc_xfree(const char *env_h5_drvr, hid_t fapl); +static unsigned test_page_small(const char *env_h5_drvr, hid_t fapl); +static unsigned test_page_large(const char *env_h5_drvr, hid_t fapl); +static unsigned test_page_large_try_extend(const char *env_h5_drvr, hid_t fapl); +static unsigned test_page_small_try_extend(const char *env_h5_drvr, hid_t fapl); +static unsigned test_page_try_shrink(const char *env_h5_drvr, hid_t fapl); +static unsigned test_page_alignment(const char *env_h5_drvr, hid_t fapl); + +/* + * Verify statistics for the free-space manager + * + */ +static int +check_stats(const H5F_t *f, const H5FS_t *frsp, H5FS_stat_t *state) +{ + H5FS_stat_t frspace_stats; /* Statistics about the heap */ + + HDassert(f); + HDassert(frsp); + + /* Get statistics for free-space and verify they are correct */ + if(H5FS_stat_info(f, frsp, &frspace_stats) < 0) + FAIL_STACK_ERROR + + if(frspace_stats.tot_space != state->tot_space) { + HDfprintf(stdout, "frspace_stats.tot_space = %Hu, state->tot_space = %Zu\n", + frspace_stats.tot_space, state->tot_space); + TEST_ERROR + } /* end if */ + if(frspace_stats.tot_sect_count != state->tot_sect_count) { + HDfprintf(stdout, "frspace_stats.tot_sect_count = %Hu, state->tot_sect_count = %Hu\n", + frspace_stats.tot_sect_count, state->tot_sect_count); + TEST_ERROR + } /* end if */ + if(frspace_stats.serial_sect_count != state->serial_sect_count) { + HDfprintf(stdout, "frspace_stats.serial_sect_count = %Hu, state->serial_sect_count = %Hu\n", + frspace_stats.serial_sect_count, state->serial_sect_count); + TEST_ERROR + } /* end if */ + if(frspace_stats.ghost_sect_count != state->ghost_sect_count) { + HDfprintf(stdout, "frspace_stats.ghost_sect_count = %Hu, state->ghost_sect_count = %Hu\n", + frspace_stats.ghost_sect_count, state->ghost_sect_count); + TEST_ERROR + } /* end if */ + + /* All tests passed */ + return(0); + +error: + return(1); +} /* check_stats() */ + +/* + *------------------------------------------------------------------------- + * To verify that blocks are allocated from file allocation + * + * Set up: + * Turn off using meta/small data aggregator + * There is nothing in free-space manager + * + * Allocate two blocks which should be from file allocation + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_eoa(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new = -1; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type; + haddr_t addr1, addr2; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + hsize_t ma_size=0; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MM_alloc() of file allocation"); + + /* Skip test when using VFDs that has different address spaces for each + * type of metadata allocation. + */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* Set the filename to use for this test */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + H5Pset_meta_block_size(fapl_new, (hsize_t)0); + H5Pset_small_data_block_size(fapl_new, (hsize_t)0); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if (new_ma_addr != ma_addr) + TEST_ERROR + + if (addr1 < (haddr_t)file_size) + TEST_ERROR + + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if (new_ma_addr != ma_addr) + TEST_ERROR + + if (addr2 < (haddr_t)file_size) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != (file_size+TBLOCK_SIZE30+TBLOCK_SIZE50)) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size) + TEST_ERROR + + if(H5Pclose(fapl_new) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support continuous address space"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Pclose(fapl_new); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_eoa() */ + +/* + *------------------------------------------------------------------------- + * To verify that an allocated block from file allocation is shrunk. + * + * Set up: + * Turn off using meta/small data aggregator + * There is nothing in free-space manager + * + * Test 1: Allocate a block of 30 from file allocation + * H5MF_try_shrink() the block by 30 : succeed + * Test 2: Allocate a block of 30 from file allocation + * H5MF_try_shrink() the block by 20 : fail + * Test 3: Allocate a block of 30 from file allocation + * H5MF_try_shrink() the block by 40 : fail + * Test 4: Allocate a block of 30 from file allocation + * H5MF_try_shrink() the block by 20 from the end: succeed + * + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_eoa_shrink(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new = -1; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size = 0, new_file_size; /* file size */ + H5FD_mem_t type; + haddr_t addr = 0; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MF_try_shrink() of file allocation: test 1"); + + /* Skip test when using VFDs that has different address spaces for each + * type of metadata allocation. + */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + H5Pset_meta_block_size(fapl_new, (hsize_t)0); + H5Pset_small_data_block_size(fapl_new, (hsize_t)0); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + if (addr < (haddr_t)file_size) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) TEST_ERROR + if (new_ma_size != ma_size) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != (file_size+TBLOCK_SIZE30)) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + /* should succeed */ + if(H5MF_try_shrink(f, type, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE30) <= 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if(new_ma_addr != ma_addr) + TEST_ERROR + if(new_ma_size != ma_size) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + TESTING("H5MF_try_shrink() of file allocation: test 2"); + + /* Skip test when using VFDs that has different address spaces for each + * type of metadata allocation. + */ + if(contig_addr_vfd) { + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + if (addr < (haddr_t)file_size) + TEST_ERROR + + /* should not succeed in shrinking */ + if(H5MF_try_shrink(f, type, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE30 - 10) > 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if (new_ma_addr != ma_addr) TEST_ERROR + if (new_ma_size != ma_size) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != (file_size + TBLOCK_SIZE30)) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + + TESTING("H5MF_try_shrink() of file allocation: test 3"); + + /* Skip test when using VFDs that has different address spaces for each + * type of metadata allocation. + */ + if(contig_addr_vfd) { + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + /* should not succeed in shrinking */ + if(H5MF_try_shrink(f, type, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE30 + 10) > 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if (new_ma_addr != ma_addr) TEST_ERROR + if (new_ma_size != ma_size) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != (file_size + TBLOCK_SIZE30)) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + TESTING("H5MF_try_shrink() of file allocation: test 4"); + + /* Skip test when using VFDs that has different address spaces for each + * type of metadata allocation. + */ + if(contig_addr_vfd) { + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + /* should succeed in shrinking */ + if(H5MF_try_shrink(f, type, H5AC_ind_read_dxpl_id, addr+10, (hsize_t)(TBLOCK_SIZE30 - 10)) <= 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &ma_size); + if(new_ma_addr != ma_addr) + TEST_ERROR + if(new_ma_size != ma_size) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != (file_size + 10)) + TEST_ERROR + + if(H5Pclose(fapl_new) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Pclose(fapl_new); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_eoa_shrink() */ + +/* + *------------------------------------------------------------------------- + * To verify that an allocated block from file allocation is extended. + * + * Set up: + * Turn off using meta/small data aggregator + * There is nothing in free-space manager + * + * Test 1: Allocate a block of 30 + * H5MF_try_extend() the block of size 30 by 50: succeed + * + * Test 2: Allocate a block of 30 + * H5MF_try_extend() the block of size 20 by 50: fail + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_eoa_extend(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new = -1; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* File size */ + H5FD_mem_t type; + haddr_t addr; + htri_t was_extended; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MF_try_extend() of file allocation: test 1"); + + /* Skip test when using VFDs that has different address spaces for each + * type of metadata allocation. + */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + if(H5Pset_meta_block_size(fapl_new, (hsize_t)0) < 0) + FAIL_STACK_ERROR + if(H5Pset_small_data_block_size(fapl_new, (hsize_t)0) < 0) + FAIL_STACK_ERROR + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + if (addr < (haddr_t)file_size) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != (file_size + TBLOCK_SIZE30)) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* should succeed */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, type, (haddr_t)addr, (hsize_t)TBLOCK_SIZE30, (hsize_t)TBLOCK_SIZE50); + + if(was_extended <= 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != (file_size + TBLOCK_SIZE30 + TBLOCK_SIZE50)) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + TESTING("H5MF_try_extend() of file allocation: test 2"); + + /* Skip test when using VFDs that has different address spaces for each + * type of metadata allocation. + */ + if(contig_addr_vfd) { + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + if(addr < (haddr_t)file_size) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if(new_ma_addr != ma_addr) + TEST_ERROR + + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, type, (haddr_t)addr, (hsize_t)(TBLOCK_SIZE30-10), (hsize_t)(TBLOCK_SIZE50)); + + /* should not succeed */ + if(was_extended > 0) + TEST_ERROR + + /* nothing should be changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size + TBLOCK_SIZE30) + TEST_ERROR + + if(H5Pclose(fapl_new) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Pclose(fapl_new); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_eoa_extend() */ + +/* + *------------------------------------------------------------------------- + * To verify that temporary blocks are allocated correctly + * + * Set up: + * There is nothing in free-space manager + * + * Tests: + * Allocate a reasonable-sized temporary block + * Check that the temporary address is high enough + * Check that file I/O with the temporary address fails + * Check that freeing a temporary address fails + * Check that closing the file doesn't change the file's size + * Check that overlapping normal & temporary address space fails: + * - Reopen the file + * - Allocate enough temporary space to use ~1/3 of the file + * - Allocate enough 'normal' space to use ~1/3 of the file + * - Check that allocating another 1/2 of the file as temporary address + * space fails + * - Check that allocating another 1/2 of the file as normal address + * space fails + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_tmp(const char *env_h5_drvr, hid_t fapl, hbool_t new_format) +{ + hid_t file = -1; /* File ID */ + hid_t fapl2 = -1; /* File access property list */ + hid_t fcpl = -1; /* File creation property list */ + + if(new_format) + TESTING("'temporary' file space allocation with new library format") + else + TESTING("'temporary' file space allocation with old library format") + + /* Can't run this test with multi-file VFDs */ + if(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi") && HDstrcmp(env_h5_drvr, "family")) { + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + haddr_t maxaddr; /* File's max. address */ + haddr_t tmp_addr; /* Temporary space file address */ + haddr_t norm_addr; /* Normal space file address */ + haddr_t check_addr; /* File address for checking for errors */ + unsigned char buf = 0; /* Buffer to read/write with */ + herr_t status; /* Generic status value */ + + /* Set the filename to use for this test */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + if(new_format) { + /* Copy the file access property list */ + if((fapl2 = H5Pcopy(fapl)) < 0) FAIL_STACK_ERROR + + /* Set the "use the latest version of the format" bounds for creating objects in the file */ + if(H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) + FAIL_STACK_ERROR + + H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, (hsize_t)1); + } /* end if */ + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, new_format?fapl2:fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Retrieve the file's maxaddr */ + if(H5F_get_maxaddr_test(file, &maxaddr) < 0) + FAIL_STACK_ERROR + + /* Allocate some temporary address space */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc_tmp(f, (hsize_t)TBLOCK_SIZE30))) + FAIL_STACK_ERROR + + /* Check if temporary file address is valid */ + if(!H5F_IS_TMP_ADDR(f, tmp_addr)) + TEST_ERROR + if(tmp_addr < (haddr_t)(maxaddr - TBLOCK_SIZE30)) + TEST_ERROR + + /* Reading & writing with a temporary address value should fail */ + H5E_BEGIN_TRY { + status = H5F_block_read(f, H5FD_MEM_SUPER, tmp_addr, sizeof(buf), H5AC_ind_read_dxpl_id, &buf); + } H5E_END_TRY; + if(status >= 0) + TEST_ERROR + H5E_BEGIN_TRY { + status = H5F_block_write(f, H5FD_MEM_SUPER, tmp_addr, sizeof(buf), H5AC_ind_read_dxpl_id, &buf); + } H5E_END_TRY; + if(status >= 0) + TEST_ERROR + + /* Freeing a temporary address value should fail */ + H5E_BEGIN_TRY { + status = H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, tmp_addr, (hsize_t)TBLOCK_SIZE30); + } H5E_END_TRY; + if(status >= 0) + TEST_ERROR + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size) + TEST_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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate 1/3 of the file as temporary address space */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc_tmp(f, (hsize_t)(maxaddr / 3)))) + FAIL_STACK_ERROR + if(!H5F_IS_TMP_ADDR(f, tmp_addr)) + TEST_ERROR + + /* Allocate 1/3 of the file as normal address space */ + if(HADDR_UNDEF == (norm_addr = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)(maxaddr / 3)))) + FAIL_STACK_ERROR + if(H5F_IS_TMP_ADDR(f, norm_addr)) + TEST_ERROR + + /* Test that pushing temporary space allocation into normal space fails */ + H5E_BEGIN_TRY { + check_addr = H5MF_alloc_tmp(f, (hsize_t)(maxaddr / 3)); + } H5E_END_TRY; + if(H5F_addr_defined(check_addr)) + TEST_ERROR + + /* Test that pushing normal space allocation into temporary space fails */ + H5E_BEGIN_TRY { + check_addr = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)(maxaddr / 3)); + } H5E_END_TRY; + if(H5F_addr_defined(check_addr)) + TEST_ERROR + + /* Free the normal block (so the file doesn't blow up to a huge size) */ + if(H5MF_xfree(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, norm_addr, (hsize_t)(maxaddr / 3)) < 0) + FAIL_STACK_ERROR + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support continuous address space"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_tmp() */ + +/* + *------------------------------------------------------------------------- + * To verify that the free-space manager is created or opened + * + * Set up: + * Turn off using meta/small data aggregator + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_fs_start(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new = -1; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FS_stat_t state; + + + TESTING("H5MF_create_fstype()/H5MF_open_fstype() of free-space manager"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + H5Pset_meta_block_size(fapl_new, (hsize_t)0); + H5Pset_small_data_block_size(fapl_new, (hsize_t)0); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size) + TEST_ERROR + + if(H5Pclose(fapl_new) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Pclose(fapl_new); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_start() */ + + +/* + *------------------------------------------------------------------------- + * To verify that a block is allocated/freed from/to the free-space manager + * + * Set up: + * Turn off using meta/small data aggregator + * + * Test 1: + * Add section A to free-space manager (addr=70, size=30) + * Allocate a block of size=30 + * The returned space's address should be same as section A's address + * Deallocate the block which will be returned to the free-space manager + * Test 2: + * Add section A to free-space manager (addr=70, size=30) + * Allocate a block of size=20 + * The returned space's address should be same as section A's address + * There should still be space of 10 left in the free-space manager + * Deallocate the block which will be returned to free-space manager + * Test 3: + * Add section A to free-space manager (addr=70, size=30) + * Allocate a block of size=40 + * The free-space manager is unable to fulfill the request + * The block is allocated from file allocation + * Deallocate the block which will be returned to free-space manager + * (the space is shrunk and freed since it is at end of file) + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_fs_alloc_free(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new = -1; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5MF_free_section_t *sect_node = NULL; + haddr_t addr; + haddr_t tmp; + H5FS_stat_t state; + + TESTING("H5MF_alloc()/H5MF_xfree() of free-space manager:test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + H5Pset_meta_block_size(fapl_new, (hsize_t)0); + H5Pset_small_data_block_size(fapl_new, (hsize_t)0); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR70, (hsize_t)TBLOCK_SIZE30); + + /* Add section A to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += TBLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Allocate a block of 30 */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is section A in free-space */ + if(addr != TBLOCK_ADDR70) + TEST_ERROR + + state.tot_space -= TBLOCK_SIZE30; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Free the block to free-space */ + H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE30); + + state.tot_space += TBLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Remove section A from free-space */ + if(H5MF_find_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30, f->shared->fs_man[H5FD_MEM_SUPER], &tmp) != TRUE) + TEST_ERROR + + if(tmp != TBLOCK_ADDR70) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_alloc()/H5MF_xfree() of free-space manager:test 2"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR70, (hsize_t)TBLOCK_SIZE30); + + /* Add section A to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += TBLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Allocate a block of 20 */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)(TBLOCK_SIZE20)); + + /* Verify that the allocated block is section A in free-space manager */ + if(addr != TBLOCK_ADDR70) + TEST_ERROR + + /* should still have 1 section of size 10 left in free-space manager */ + state.tot_space -= (TBLOCK_SIZE20); + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Free the block to free-space manager */ + H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, addr, (hsize_t)(TBLOCK_SIZE20)); + + /* Still 1 section in free-space because of merging */ + state.tot_space += TBLOCK_SIZE20; + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Remove section A from free-space */ + if(H5MF_find_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30, f->shared->fs_man[H5FD_MEM_SUPER], &tmp) != TRUE) + TEST_ERROR + + if(tmp != TBLOCK_ADDR70) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_alloc()/H5MF_xfree() of free-space manager:test 3"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR70, (hsize_t)TBLOCK_SIZE30); + + /* Add section A to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += TBLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* + * Allocate a block of 40. + * Since free-space manager cannot fulfull the request, + * the block is obtained from file allocation + */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)(TBLOCK_SIZE40)); + + /* Verify that the allocated block is not section A in free-space */ + if(addr == TBLOCK_ADDR70) + TEST_ERROR + + /* free-space info should be the same */ + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Remove section A from free-space */ + if(H5MF_find_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30, f->shared->fs_man[H5FD_MEM_SUPER], &tmp) != TRUE) + TEST_ERROR + + /* Verify that the block is section A in free-space */ + if(tmp != TBLOCK_ADDR70) + TEST_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Free the block of size 40 to free-space */ + H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, addr, (hsize_t)(TBLOCK_SIZE40)); + + /* + * Free-space info is the same. + * The block is returned to free-space. + * It is shrunk and freed because it is at end of file. + */ + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size) + TEST_ERROR + + if(H5Pclose(fapl_new) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Pclose(fapl_new); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_alloc_free() */ + + +/* + *------------------------------------------------------------------------- + * To verify that a block allocated from the free-space manager can be extended + * + * Set up: + * Turn off using meta/small data aggregator + * + * Test 1: + * Add section A to free-space manager: addr=70, size=30 + * Allocate a block of size 30 from free-space manager + * Add section B to free-space manager: addr=100, size=50 + * Try to extend the allocated block by requested-size=50 + * Succeed: section A adjoins section B (70+30=100 which is section B's address) and + * requested-size (50) is equal to the size of section B + * Test 2: + * Add section A to free-space manager: addr=70, size=30 + * Allocate a block of size 30 from free-space manager + * Add section B to free-space manager: addr=100, size=50 + * Try to extend the allocated block by requested-size=60 + * Fail: section A adjoins section B (70+30=100 which is section B's address) but + * requested-size (60) > size of section B (50) + * + * Test 3: + * Add section A to free-space manager: addr=70, size=30 + * Allocate a block of size 30 from free-space manager + * Add section B to free-space manager: addr=100, size=50 + * Try to extend the allocated block by requested-size=40 + * Succeed: section A adjoins section B (70+30=100 which is section B's address) and + * requested-size (40) < size of section B (50), therefore, + * a section of 10 is left in the free-space manager + * Test 4: + * Add section A to free-space manager: addr=70, size=20 + * Allocate a block of size 20 from free-space manager + * Add section B to free-space manager: addr=100, size=50 + * Try to extend the allocated block by 50 from the free-space_manager: + * Fail: section A does not adjoin section B (70+20 != address of section B) even though + * the requested-size (50) equal to size of section B (50) + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_fs_extend(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl_new = -1; /* copy of fapl */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5MF_free_section_t *sect_node1 = NULL, *sect_node2=NULL; + haddr_t addr; + haddr_t tmp; + H5FS_stat_t state; /* State of free space*/ + htri_t was_extended; + + TESTING("H5MF_try_extend() of free-space manager:test 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Turn off using meta/small data aggregator */ + H5Pset_meta_block_size(fapl_new, (hsize_t)0); + H5Pset_small_data_block_size(fapl_new, (hsize_t)0); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node1 = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR70, (hsize_t)TBLOCK_SIZE30); + + /* Add section A to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node1)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += TBLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Allocate a block of 30 */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is section A in free-space manager */ + if(addr != TBLOCK_ADDR70) + TEST_ERROR + + state.tot_space -= TBLOCK_SIZE30; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Create section B */ + sect_node2 = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR100, (hsize_t)TBLOCK_SIZE50); + + /* Add section B to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node2)) + FAIL_STACK_ERROR + + state.tot_space += TBLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Try to extend the allocated block */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_SUPER, (haddr_t)TBLOCK_ADDR70, (hsize_t)TBLOCK_SIZE30, (hsize_t)TBLOCK_SIZE50); + + /* should succeed */ + if(was_extended <= 0) + TEST_ERROR + + /* Section B is removed from free-space manager */ + state.tot_space -= TBLOCK_SIZE50; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Free the extended block to free-space manager */ + H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, addr, (hsize_t)(TBLOCK_SIZE30+TBLOCK_SIZE50)); + + /* Verify that the extended block is back into free-space */ + state.tot_space += (TBLOCK_SIZE30+TBLOCK_SIZE50); + state.tot_sect_count = 1; + state.serial_sect_count = 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Remove the extended block */ + if(H5MF_find_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)(TBLOCK_SIZE30+TBLOCK_SIZE50), f->shared->fs_man[H5FD_MEM_SUPER], &tmp) != TRUE) + TEST_ERROR + + if(tmp != TBLOCK_ADDR70) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_try_extend() of free-space manager:test 2"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node1 = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR70, (hsize_t)TBLOCK_SIZE30); + + /* Add section A to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node1)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += TBLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Allocate a block of 30 */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is section A in free-space manager */ + if(addr != TBLOCK_ADDR70) + TEST_ERROR + + state.tot_space -= TBLOCK_SIZE30; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Create section B */ + sect_node2 = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR100, (hsize_t)TBLOCK_SIZE50); + + /* Add section B to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node2)) + FAIL_STACK_ERROR + + state.tot_space += TBLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Try to extend the allocated block */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_SUPER, (haddr_t)TBLOCK_ADDR70, (hsize_t)TBLOCK_SIZE30, (hsize_t)(TBLOCK_SIZE50+10)); + + /* Should not be able to extend the allocated block */ + if(was_extended) + TEST_ERROR + + /* free-space info should remain the same */ + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Free the allocated block A to free-space */ + H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE30); + + /* the returned section A is merged with section B in free-space */ + /* rest of the info remains the same */ + state.tot_space += TBLOCK_SIZE30; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Remove the merged sections A & B from free-space */ + if(H5MF_find_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)(TBLOCK_SIZE30+TBLOCK_SIZE50), f->shared->fs_man[H5FD_MEM_SUPER], &tmp) != TRUE) + TEST_ERROR + + if(tmp != addr) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_try_extend() of free-space manager:test 3"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node1 = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR70, (hsize_t)TBLOCK_SIZE30); + + /* Add section A to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node1)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += TBLOCK_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Allocate a block of 30 */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is section A in free-space manager */ + if(addr != TBLOCK_ADDR70) + TEST_ERROR + + state.tot_space -= TBLOCK_SIZE30; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Create section B */ + sect_node2 = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR100, (hsize_t)TBLOCK_SIZE50); + + /* Add section B to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node2)) + FAIL_STACK_ERROR + + state.tot_space += TBLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Try to extend the allocated block */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_SUPER, (haddr_t)TBLOCK_ADDR70, (hsize_t)TBLOCK_SIZE30, (hsize_t)(TBLOCK_SIZE40)); + + /* Should succeed in extending the allocated block */ + if(was_extended <=0) + TEST_ERROR + + /* Should have 1 section of size=10 left in free-space manager */ + state.tot_space -= (TBLOCK_SIZE40); + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Free the extended block */ + H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, addr, (hsize_t)(TBLOCK_SIZE30+TBLOCK_SIZE40)); + + /* rest info is same, the extended section returned is merged with the section in free-space */ + state.tot_space += (TBLOCK_SIZE30+TBLOCK_SIZE40); + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Remove the merged sections A & B from free-space */ + if(H5MF_find_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)(TBLOCK_SIZE30+TBLOCK_SIZE50), f->shared->fs_man[H5FD_MEM_SUPER], &tmp) != TRUE) + TEST_ERROR + + if(tmp != addr) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + + TESTING("H5MF_try_extend() of free-space manager:test 4"); + + /* Re-open the file with meta/small data setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node1 = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR70, (hsize_t)(TBLOCK_SIZE30-10)); + + /* Add section A of size=20 to free-space */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node1)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += (TBLOCK_SIZE30-10); + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Allocate a block of size=20 */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)(TBLOCK_SIZE30-10)); + + /* Verify that the allocated block is section A in free-space manager */ + if(addr != TBLOCK_ADDR70) + TEST_ERROR + + state.tot_space -= (TBLOCK_SIZE30-10); + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Create section B */ + sect_node2 = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR100, (hsize_t)TBLOCK_SIZE50); + + /* Add section B to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node2)) + FAIL_STACK_ERROR + + state.tot_space += TBLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Try to extend the allocated block */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_SUPER, (haddr_t)TBLOCK_ADDR70, (hsize_t)(TBLOCK_SIZE30-10), (hsize_t)TBLOCK_SIZE50); + + /* Should not succeed in extending the allocated block */ + if(was_extended) + TEST_ERROR + + /* Free-space info should be the same */ + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Free the allocated block */ + H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, addr, (hsize_t)(TBLOCK_SIZE30-10)); + + state.tot_space += (TBLOCK_SIZE30-10); + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Remove section A from free-space manger */ + if(H5MF_find_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)(TBLOCK_SIZE30-10), f->shared->fs_man[H5FD_MEM_SUPER], &tmp) != TRUE) + TEST_ERROR + + if(tmp != addr) TEST_ERROR + + /* Remove section B from free-space manager */ + if(H5MF_find_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50, f->shared->fs_man[H5FD_MEM_SUPER], &tmp) != TRUE) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl_new)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size) + TEST_ERROR + + if(H5Pclose(fapl_new) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Pclose(fapl_new); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_extend() */ + +/* + *------------------------------------------------------------------------- + * To verify that an aggregator is absorbed into a section. + * + * Test 1: To aborb the aggregator onto the beginning of the section + * Allocate block A from meta_aggr + * Create a free-space section node with an address that adjoins + * the end of meta_aggr and a size to make the aggregator + * get absorbed into the section. + * The adding of the section to free-space will call H5MF_aggr_absorb(), + * which will absorb meta_aggr to the section: + * section size + remaining size of aggregator is > aggr->alloc_size, + * section is allowed to absorb an aggregator (allow_sect_absorb is true) + * + * Test 2: To absorb the aggregator onto the end of the section + * Allocate block A from meta_aggr + * Allocate block B from sdata_aggr + * Create a free-space section node with an address that adjoins + * the beginning of meta_aggr and a size to make the + * aggregator get absorbed into the section. + * The adding of the section to free-space will call H5MF_aggr_absorb(), + * which will absorb meta_aggr to the section: + * section size + remaining size of aggregator is > aggr->alloc_size, + * section is allowed to absorb an aggregator (allow_sect_absorb is true) + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_fs_absorb(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + haddr_t addr, saddr; + haddr_t tmp; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0; + H5MF_free_section_t *sect_node=NULL; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("A free-space section absorbs an aggregator: test 1"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* 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 + + /* Close 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Allocate a section from meta_aggr */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + /* Create a section */ + sect_node = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)(ma_addr+ma_size), (hsize_t)TBLOCK_SIZE2048); + + /* Add a section to free-space that adjoins end of the aggregator */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node)) + FAIL_STACK_ERROR + + /* Verify that the section did absorb the aggregator */ + if(H5MF_find_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)(ma_addr+ma_size), f->shared->fs_man[H5FD_MEM_SUPER], &tmp) != TRUE) + TEST_ERROR + + if(tmp != ma_addr) TEST_ERROR + + /* Restore info for aggregator */ + f->shared->meta_aggr.addr = ma_addr; + f->shared->meta_aggr.size = ma_size; + + /* Remove section from meta_aggr */ + H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE30); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + TESTING("A free-space section absorbs an aggregator: test 2"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + if(contig_addr_vfd) { + /* 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Allocate a section from meta_aggr */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + /* Allocate a section from sdata_aggr */ + saddr = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Add a section to free-space that adjoins the beginning of meta_aggr */ + sect_node = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)addr, (hsize_t)TBLOCK_SIZE30); + + /* When adding, meta_aggr is absorbed onto the end of the section */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node)) + FAIL_STACK_ERROR + + /* Verify that the section did absorb the aggregator */ + if(H5MF_find_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)(ma_size+TBLOCK_SIZE30), f->shared->fs_man[H5FD_MEM_SUPER], &tmp) != TRUE) + TEST_ERROR + + if((tmp + TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* restore info to meta_aggr */ + f->shared->meta_aggr.addr = ma_addr; + f->shared->meta_aggr.size = ma_size; + + /* Remove section from meta_aggr */ + H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE30); + /* Remove section from sdata_aggr */ + H5MF_xfree(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, saddr, (hsize_t)TBLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_absorb() */ + +/* + *------------------------------------------------------------------------- + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * The first block of 30 is allocated from meta_aggr + * There is space of 2018 left in meta_aggr + * + * Allocate second block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr + * Result: + * The second block of 50 is allocated from meta_aggr + * There is space of 1968 left in meta_aggr + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_aggr_alloc1(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + hid_t fcpl; /* File creation property list */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type; + haddr_t addr1, addr2; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 1"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* File creation property list template */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + TEST_ERROR + + /* Set to H5F_FSPACE_STRATEGY_AGGR strategy */ + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_AGGR, FALSE, (hsize_t)1) < 0) + TEST_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of a file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + TEST_ERROR + + /* Allocate first block from meta_aggr */ + type = H5FD_MEM_SUPER; + if((addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30)) == HADDR_UNDEF) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if((addr1+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate second block from meta_aggr */ + if((addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50)) == HADDR_UNDEF) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if((addr2+TBLOCK_SIZE50) != ma_addr) + TEST_ERROR + if(ma_size != (TBLOCK_SIZE2048 - (TBLOCK_SIZE30 + TBLOCK_SIZE50))) + TEST_ERROR + + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != (file_size+TBLOCK_SIZE30+TBLOCK_SIZE50)) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + TEST_ERROR + + /* Free the two blocks: order matters because of H5F_FSPACE_STRATEGY_AGGR strategy */ + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE50) < 0) + TEST_ERROR + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30) < 0) + TEST_ERROR + + if(H5Fclose(file) < 0) + TEST_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + if(H5Pclose(fcpl) < 0) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + H5Pclose(fcpl); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc1() */ + +/* + *------------------------------------------------------------------------- + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * There is space of 2018 left in meta_aggr + * + * Allocate second block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr + * Result: + * The second block of 50 is allocated from what is left in meta_aggr + * There is space of 1968 left in meta_aggr + * + * Allocate third block (2058) from meta_aggr: + * request-size is > what is left in meta_aggr and is >= meta_aggr->alloc_size + * meta_aggr is at EOA + * Result: + * A block of request-size is extended via file allocation and is merged with meta_aggr + * The block of 2058 is allocated out of meta_aggr + * There is space of 1968 left in meta_aggr + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_aggr_alloc2(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type; + haddr_t addr1, addr2, addr3; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 2"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* 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 + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file */ + if((file_size= h5_get_file_size(filename, fapl)) < 0) + TEST_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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if((addr1+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if((addr2+TBLOCK_SIZE50) != ma_addr) + TEST_ERROR + + if (ma_size != (TBLOCK_SIZE2048 - (TBLOCK_SIZE30 + TBLOCK_SIZE50))) + TEST_ERROR + + addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2058); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr3+TBLOCK_SIZE2058) != ma_addr) + TEST_ERROR + + if(ma_size != (TBLOCK_SIZE2048 - (TBLOCK_SIZE30 + TBLOCK_SIZE50))) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + /* Unused space is freed from the end of the file */ + if(new_file_size != (file_size+TBLOCK_SIZE30+TBLOCK_SIZE50+TBLOCK_SIZE2058)) + TEST_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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30+TBLOCK_SIZE50+TBLOCK_SIZE2058); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc2() */ + +/* + *------------------------------------------------------------------------- + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr : (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * There is space of 2018 left in meta_aggr + * + * Allocate second block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr + * Result: + * The second block of 50 is allocated from what is left in meta_aggr + * There is space of 1968 left in meta_aggr + * + * Allocate first block (30) from sdata_aggr: (nothing in sdata_aggr) + * request-size is > what is left in other_aggr and is < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * There is space of 2018 left in sdata_aggr + * + * Allocate the third block (2058) from meta_aggr: + * request-size is > what is left in meta_aggr and >= meta_aggr->alloc_size + * sdata_aggr is at EOA but has not used up more than sdata_aggr->alloc_size + * Result: A block of request-size is obtained via file allocation + * The new block's address is returned + * Nothing is changed in meta_aggr and sdata_aggr + * + * Allocate fourth block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * The fourth block of 50 is allocated from what is left in meta_aggr + * There is space of 1968 left in meta_aggr + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_aggr_alloc3(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3, addr4, saddr1; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0; + haddr_t sdata_addr=HADDR_UNDEF; + hsize_t sdata_size=0; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MF_alloc() of meta/sdata aggregator: test 3"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* 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 + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate second block from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr2+TBLOCK_SIZE50) != ma_addr) + TEST_ERROR + if(ma_size != (TBLOCK_SIZE2048 - (TBLOCK_SIZE30 + TBLOCK_SIZE50))) + TEST_ERROR + + /* Allocate first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if((saddr1+TBLOCK_SIZE30) != sdata_addr) + TEST_ERROR + if(sdata_size != (TBLOCK_SIZE2048 - TBLOCK_SIZE30)) TEST_ERROR + + /* Allocate third block, which is from file allocation not from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)(TBLOCK_SIZE2058)); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + /* info for meta_aggr shouldn't be changed */ + if(addr3 != (sdata_addr+sdata_size)) TEST_ERROR + if((addr3+TBLOCK_SIZE2058) == new_ma_addr) TEST_ERROR + if((new_ma_addr != ma_addr) || (new_ma_size != ma_size)) TEST_ERROR + + /* Allocate fourth block, which should be from meta_aggr */ + addr4 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr4+TBLOCK_SIZE50) != ma_addr) + TEST_ERROR + if(ma_size != (TBLOCK_SIZE2048 - (TBLOCK_SIZE30 + TBLOCK_SIZE50 + TBLOCK_SIZE50))) + TEST_ERROR + + /* Free all the allocated blocks */ + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE50); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE2058); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr4, (hsize_t)TBLOCK_SIZE50); + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE30); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc3() */ + + +/* + *------------------------------------------------------------------------- + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * There is space of 2018 left in meta_aggr + * The first block of 30 is allocated from there + * + * Allocate first block (30) from sdata_aggr: (nothing in sdata_aggr) + * request-size is > what is left in sdata_aggr and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * + * Allocate the second block (2018) from sdata_aggr: + * request-size is <= what is left in sdata_aggr and < sdata_aggr->alloc_size + * request-size is < sdata_aggr->alloc_size + * Result: + * The block is allocated from what is left in sdata_aggr (all used up) + * + * Allocate third block (50) from sdata_aggr : + * request-size is > what is left in sdata_aggr and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is extended via file allocation + * The third block of 50 is allocated from there + * There is space of 1998 left in the sdata_aggr + * + * Allocate second block (2058) from meta_aggr: + * request-size is > what is left in meta_aggr and >= meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * unused spaced in sdata_aggr is freed to free-space and is shrunk + * sdata_aggr is reset to 0 + * A block of request-size is obtained via file allocation + * The new block's address is returned + * The block does not adjoin meta_aggr + * meta_aggr's info is unchanged + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_aggr_alloc4(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* File size */ + H5FD_mem_t type, stype; + haddr_t addr1, addr2, saddr1, saddr2, saddr3; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0, sdata_size=0; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 4"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* 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 + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr1+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + if(ma_size != (TBLOCK_SIZE2048 - TBLOCK_SIZE30)) + TEST_ERROR + + /* Allocate first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if((saddr1+TBLOCK_SIZE30) != sdata_addr) + TEST_ERROR + + /* Allocate second block from sdata_aggr */ + saddr2 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)(TBLOCK_SIZE2048 - TBLOCK_SIZE30)); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if(saddr2+(TBLOCK_SIZE2048 - TBLOCK_SIZE30) != sdata_addr) + TEST_ERROR + + /* Allocate third block from sdata_aggr */ + saddr3 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + + if((saddr3+TBLOCK_SIZE50) != sdata_addr) + TEST_ERROR + if(sdata_size != (TBLOCK_SIZE2048 - TBLOCK_SIZE50)) + TEST_ERROR + + /* Allocate second block of 2058, which is from file allocation, not from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2058); + + if(addr2 != sdata_addr) + TEST_ERROR + + /* sdata_aggr is reset 0 */ + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if((sdata_addr != 0) && (sdata_size != 0)) + TEST_ERROR + + /* info is unchanged in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if((new_ma_addr != ma_addr) && (new_ma_size != ma_size)) + TEST_ERROR + + /* Free all the allocated blocks */ + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE2058); + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr2, (hsize_t)TBLOCK_SIZE2048 - TBLOCK_SIZE30); + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr3, (hsize_t)TBLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc4() */ + +/* + *------------------------------------------------------------------------- + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocate from there + * + * Allocate second block (50) from meta_aggr: + * request-size is < what is left in meta_aggr + * Result: + * The second block of 50 is allocated from what is left there + * There is space of 1968 left in the meta_aggr + * + * Allocate third block (1970) from meta_aggr: + * request-size is > what is left in meta_aggr and is < meta_aggr->alloc_size + * Result: A block of meta_aggr->alloc_size is extended via file allocation and is absorbed into the meta_aggr + * The block of 1970 is allocated from there + * There is space of 2046 left in meta_aggr + * + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_aggr_alloc5(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* File size */ + H5FD_mem_t type; + haddr_t addr1, addr2, addr3; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 5"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* 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 + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if((addr1+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate second block from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if(addr2+TBLOCK_SIZE50 != ma_addr) + TEST_ERROR + if(ma_size != (TBLOCK_SIZE2048 - (TBLOCK_SIZE30+TBLOCK_SIZE50))) + TEST_ERROR + + /* Allocate third block from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1970); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if(addr3 != ma_addr) TEST_ERROR + if((addr3+TBLOCK_SIZE1970) != new_ma_addr) TEST_ERROR + if(new_ma_size != (TBLOCK_SIZE2048 - (TBLOCK_SIZE1970 - ma_size))) + TEST_ERROR + + /* Free all the allocated blocks */ + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE50); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE1970); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc5() */ + +/* + *------------------------------------------------------------------------- + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * + * Allocate second block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr + * Result: + * The second block of 50 is allocated from what is left in meta_aggr + * There is space of 1968 left in meta_aggr + * + * Allocate first block (30) from sdata_aggr: (nothing in sdata_aggr) + * request-size is > what is left in sdata_aggr and is < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * There is space of 2018 left in sdata_aggr + * + * Allocate third block (1970) from meta_aggr: + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * sdata_aggr is at EOA but has not used up more than sdata_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation. + * The block does not adjoin meta_aggr + * sdata_aggr is untouched + * meta_aggr's unused space of [880, 1968] is freed to free-space + * meta_aggr is updated to point to the new block + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_aggr_alloc6(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; /* file size */ + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3, saddr1; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0, sdata_size=0; + H5FS_stat_t state; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 6"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* 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 + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + type = H5FD_MEM_SUPER; + + /* Allocate first block from meta_aggr */ + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if((addr1+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate second block from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if(addr2+TBLOCK_SIZE50 != ma_addr) + TEST_ERROR + if(ma_size != (TBLOCK_SIZE2048 - (TBLOCK_SIZE30 + TBLOCK_SIZE50))) + TEST_ERROR + + /* Allocate first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if((saddr1+TBLOCK_SIZE30) != sdata_addr) TEST_ERROR + if(sdata_size != (TBLOCK_SIZE2048 - TBLOCK_SIZE30)) TEST_ERROR + + /* Allocate third block from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1970); + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if((addr3+TBLOCK_SIZE1970) != new_ma_addr) TEST_ERROR + if(addr3 != (sdata_addr+sdata_size)) TEST_ERROR + + if((ma_addr+TBLOCK_SIZE1970) == new_ma_addr) TEST_ERROR + if(new_ma_size != (TBLOCK_SIZE2048 - TBLOCK_SIZE1970)) + TEST_ERROR + + /* Verify that meta_aggr's unused space of 1968 is freed to free-space */ + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += (TBLOCK_SIZE2048 - (TBLOCK_SIZE30+TBLOCK_SIZE50)); + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free all the allocated blocks */ + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE50); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE1970); + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE30); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((new_file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(new_file_size != file_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc6() */ + +/* + *------------------------------------------------------------------------- + * To verify that blocks are allocated from the aggregator + * + * Allocate first block (30) from meta_aggr: (nothing in meta_aggr) + * request-size is > what is left in meta_aggr and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from there + * + * Allocate second block (50) from meta_aggr: + * request-size is <= what is left in meta_aggr + * Result: + * The second block of 50 is allocated from what is left in the aggregator + * There is space of 1968 left in the meta_aggr + * + * Allocate first block (30) from sdata_aggr: (nothing in sdata_aggr) + * request-size is > what is left in sdata_aggr->size and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocate from there + * + * Allocate second block (2018) from sdata_aggr: + * request-size is <= what is left in sdata_aggr and is < sdata_aggr->alloc_size + * Result: + * The second block of 2018 is allocated from what is left in sdata_aggr (all used up) + * + * Allocate third block (50) from sdata_aggr: + * request-size is > what is left in sdata_aggr and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is extended via file allocation + * The third block of 50 is allocated from there + * + * Allocate third block (1970) from meta_aggr: + * request-size is > what is left in meta_aggr and is < meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * unused space in sdata_aggr is freed to free-space and is shrunk + * sdata_aggr is reset to 0 + * A block of meta_aggr->alloc_size is obtained via file allocation + * The block does not adjoin meta_aggr + * meta_aggr's unused space of [880, 1968] is freed to free-space + * meta_aggr is updated to point to the new block + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_aggr_alloc7(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t empty_size, file_size; + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3, saddr1, saddr2, saddr3; + haddr_t ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, sdata_size=0; + H5FS_stat_t state; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MF_alloc() of meta/sdata aggregator:test 7"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* 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 + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((empty_size = h5_get_file_size(filename, fapl)) < 0) + TEST_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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate the first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate the second block from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if (addr2+TBLOCK_SIZE50 != ma_addr) + TEST_ERROR + if (ma_size != (TBLOCK_SIZE2048 - (TBLOCK_SIZE30 + TBLOCK_SIZE50))) + TEST_ERROR + + /* Allocate the first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr1+TBLOCK_SIZE30) != sdata_addr) + TEST_ERROR + + /* Allocate the second block from sdata_aggr */ + saddr2 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2048 - TBLOCK_SIZE30); + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr2+(TBLOCK_SIZE2048 - TBLOCK_SIZE30)) != sdata_addr) + TEST_ERROR + if (sdata_size != 0) TEST_ERROR + + /* Allocate the third block from sdata_aggr */ + saddr3 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr3+TBLOCK_SIZE50) != sdata_addr) + TEST_ERROR + if (sdata_size != (TBLOCK_SIZE2048 - TBLOCK_SIZE50)) + TEST_ERROR + + /* Allocate the third block from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1970); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if (addr3 != sdata_addr) TEST_ERROR + if ((addr3 + TBLOCK_SIZE1970) != ma_addr) TEST_ERROR + if (ma_size != (TBLOCK_SIZE2048 - TBLOCK_SIZE1970)) TEST_ERROR + + /* sdata_aggr info is reset to 0 */ + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if (sdata_addr != HADDR_UNDEF) TEST_ERROR + if (sdata_size != 0) TEST_ERROR + + /* Verify that meta_aggr's unused space of 1968 is freed to free-space */ + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += (TBLOCK_SIZE2048 - (TBLOCK_SIZE30 + TBLOCK_SIZE50)); + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[type], &state)) + TEST_ERROR + + /* Free all the allocated blocks */ + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE50); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE1970); + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr2, (hsize_t)(TBLOCK_SIZE2048 - TBLOCK_SIZE30)); + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr3, (hsize_t)TBLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (file_size != empty_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_alloc7() */ + +/* + *------------------------------------------------------------------------- + * To verify that a block can be extended from the aggregator + * + * Test 1: Allocate block A from meta_aggr which is at end of file + * Try to extend the block which adjoins the aggregator that is at end of file + * a. block size < (% * aggr->alloc_size) + * The block is allocated from the aggregator + * b. block size > (% * aggr->alloc_size) but block size < aggr->alloc_size + * The block is extended by aggr->alloc_size and the block is allocated from the aggregator + * c. block size > (% * aggr->alloc_size) but block size > aggr->alloc_size + * The block is extended by extended-request and the block is allocated from the aggregator + * + * Test 2: Allocate block A from meta_aggr + * Allocate block B from sdata_aggr so that meta_aggr is not at end of file + * Try to extend a block which adjoins meta_aggr and meta_aggr can fulfill the extended-request + * H5MF_try_extend() succeeds: the block is extended into the aggregator + * + * Test 3: Allocate block A from meta_aggr + * Allocate block B from sdata_aggr so that meta_aggr is not at end of file + * Try to extend a block which adjoins meta_aggr but meta_aggr cannot fulfill the extended-request + * H5MF_try_extend() fails + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_aggr_extend(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t empty_size = 0, file_size; + H5FD_mem_t type, stype; + haddr_t new_addr, addr, saddr; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0, sdata_size=0; + htri_t was_extended; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MF_try_extend() of meta/sdata aggregator: test 1"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* 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 + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((empty_size = h5_get_file_size(filename, fapl)) < 0) + TEST_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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate the first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if((addr+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Adjust meta_aggr's info info for testing */ + f->shared->meta_aggr.addr = addr; + f->shared->meta_aggr.size = f->shared->meta_aggr.alloc_size; + + new_addr = addr - 10; + + /* Try to extend the block by an amount < (% * aggr->alloc_size) */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, type, (haddr_t)new_addr, (hsize_t)10, (hsize_t)(TBLOCK_SIZE50)); + + /* should succeed */ + if(!was_extended) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if(new_ma_addr != (addr+TBLOCK_SIZE50)) + TEST_ERROR + if(new_ma_size != (f->shared->meta_aggr.alloc_size - TBLOCK_SIZE50)) TEST_ERROR + + /* Free the allocated blocks */ + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE50); + + /* Try to extend the block by an amount > (% * aggr->alloc_size) but amount < aggr->alloc_size */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, type, (haddr_t)new_addr, (hsize_t)10, (hsize_t)(TBLOCK_SIZE700)); + + /* should succeed */ + if(!was_extended) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if(new_ma_addr != (addr + TBLOCK_SIZE700)) + TEST_ERROR + if(new_ma_size != (f->shared->meta_aggr.alloc_size * 2 - TBLOCK_SIZE700)) TEST_ERROR + + /* Free the allocated blocks */ + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE700); + + /* Try to extend the block by an amount > (% * aggr->alloc_size) but amount > aggr->alloc_size */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, type, (haddr_t)new_addr, (hsize_t)10, (hsize_t)(TBLOCK_SIZE2058)); + + /* should succeed */ + if(!was_extended) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if (new_ma_addr != (addr + TBLOCK_SIZE2058)) + TEST_ERROR + if (new_ma_size != f->shared->meta_aggr.size) TEST_ERROR + + /* Free the allocated blocks */ + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE2058); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if (file_size != empty_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + TESTING("H5MF_try_extend() of meta/sdata aggregator: test 2"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + if(contig_addr_vfd) { + /* 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate the first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if((addr+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate the first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if((saddr+TBLOCK_SIZE50) != sdata_addr) + TEST_ERROR + + /* Adjust meta_aggr's info info for testing */ + f->shared->meta_aggr.addr = addr; + f->shared->meta_aggr.size = f->shared->meta_aggr.alloc_size; + + new_addr = addr - 10; + + /* should be able to fulfill request from the aggreqator itself */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, type, (haddr_t)new_addr, (hsize_t)10, (hsize_t)(TBLOCK_SIZE50)); + + if(!was_extended) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if(new_ma_addr != (addr+TBLOCK_SIZE50)) + TEST_ERROR + if(new_ma_size != (f->shared->meta_aggr.alloc_size-TBLOCK_SIZE50)) + TEST_ERROR + + /* Restore info for meta_aggr */ + f->shared->meta_aggr.addr = ma_addr; + f->shared->meta_aggr.size = ma_size; + + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr, (hsize_t)TBLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(file_size != empty_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + TESTING("H5MF_try_extend() of meta/sdata aggregator: test 3"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + if(contig_addr_vfd) { + /* 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate first block from meta_aggr */ + type = H5FD_MEM_SUPER; + addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate first block from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if((saddr+TBLOCK_SIZE50) != sdata_addr) + TEST_ERROR + + /* Adjust meta_aggr's info info for testing */ + f->shared->meta_aggr.addr = addr; + f->shared->meta_aggr.size = 0; + + new_addr = addr - 10; + + /* unable to fulfill request from the aggreqator itself */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, type, (haddr_t)new_addr, (hsize_t)10, (hsize_t)(TBLOCK_SIZE50)); + + if(was_extended) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if (new_ma_addr != addr) TEST_ERROR + if (new_ma_size != 0) TEST_ERROR + + /* restore info for meta_aggr */ + f->shared->meta_aggr.addr = ma_addr; + f->shared->meta_aggr.size = ma_size; + + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr, (hsize_t)TBLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(file_size != empty_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_extend() */ + +/* + *------------------------------------------------------------------------- + * To verify that a block is absorbed into an aggregator + * + * MF_try_shrink() only allows blocks to be absorbed into an aggregator + * + * Test 1: H5MF_alloc() block A from meta_aggr + * H5MF_try_shrink() block A should merge it back into meta_aggr + * since block A adjoins the beginning of meta_aggr + * + * Test 2: H5MF_alloc() block A from meta_aggr + * H5MF_alloc() block B from sdata_aggr + * H5MF_try_shrink() block B should merge it back to the end of sdata_aggr + * because sec2 driver is FLMAP_DICHOTOMY by default + * + * Test 3: H5MF_alloc() block A from meta_aggr + * H5MF_alloc() block B from meta_aggr + * H5MF_alloc() block C from meta_aggr + * H5MF_try_shrink() block B should fail since it does not adjoin the + * beginning nor the end of meta_aggr + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_aggr_absorb(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t empty_size = 0, file_size; + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3, saddr1; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + haddr_t new_sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0; + hsize_t sdata_size=0, new_sdata_size=0; + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + + TESTING("H5MF_try_shrink() of meta/sdata aggregator: test 1"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(contig_addr_vfd) { + /* 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 + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((empty_size = h5_get_file_size(filename, fapl)) < 0) + TEST_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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate block A from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + ma_addr = new_ma_addr - TBLOCK_SIZE30; + + if((addr1 + TBLOCK_SIZE30) != new_ma_addr) + TEST_ERROR + + /* should succeed */ + if(H5MF_try_shrink(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30) <= 0) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + + if(new_ma_addr != ma_addr) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(file_size != empty_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + TESTING("H5MF_try_shrink() of meta/sdata aggregator: test 2"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + if(contig_addr_vfd) { + /* 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate block A from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr1+TBLOCK_SIZE30) != ma_addr) TEST_ERROR + if(ma_size != (TBLOCK_SIZE2048 - TBLOCK_SIZE30)) TEST_ERROR + + /* Allocate block B from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), NULL, &sdata_size); + + /* should succeed */ + if(H5MF_try_shrink(f, stype, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE50) <= 0) + TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &new_sdata_addr, &new_sdata_size); + if(new_sdata_addr != saddr1) TEST_ERROR + if(new_sdata_size != sdata_size + TBLOCK_SIZE50) TEST_ERROR + + /* meta_aggr info should be updated because the block is absorbed into the meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr) TEST_ERROR + if (new_ma_size != (ma_size)) TEST_ERROR + + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(file_size != empty_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + TESTING("H5MF_try_shrink() of meta/sdata aggregator: test 3"); + + /* Skip test when using VFDs that don't use the metadata aggregator */ + if(contig_addr_vfd) { + /* 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate block A from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr1+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* Allocate block B from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if((addr2+TBLOCK_SIZE50) != ma_addr) + TEST_ERROR + + /* Allocate block C from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)(TBLOCK_SIZE30+TBLOCK_SIZE50)); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if((addr3+TBLOCK_SIZE30+TBLOCK_SIZE50) != ma_addr) + TEST_ERROR + + /* should not succeed */ + if(H5MF_try_shrink(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE50) > 0) + TEST_ERROR + + /* aggregator info should be the same as before */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if(new_ma_addr != ma_addr) TEST_ERROR + + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE50); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)(TBLOCK_SIZE30+TBLOCK_SIZE50)); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(file_size != empty_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support metadata aggregator"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_aggr_absorb() */ + +/* + *------------------------------------------------------------------------- + * To verify that a block allocated from file allocation is aligned, can be shrunk and extended + * + * Alignment = 1024 or 4096 + * + * Test 1: + * Turn off using meta data aggregator + * Allocate a block of 30 which should be from file allocation + * Result: + * The return address should be aligned + * A fragment [800, 224] or [800, 3296] is freed to free-space + * EOA is 1054 or 4126 + * + * Allocate a block of 50 which should be from file allocation + * Result: + * The return address should be aligned + * A fragment [1054, 994] or [4126, 4066] is freed to free-space + * EOA is 2098 or 8242 + * Test 2: + * Turn off using meta data aggregator + * Allocate a block which should be from file allocation + * The return address should be aligned + * H5MF_try_shrink() the block with aligned address should succeed + * + * Test 3: + * Turn off using meta data aggregator + * Allocate a block which should be from file allocation + * The return address should be aligned + * H5MF_try_extend() the block with aligned address should succeed + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_align_eoa(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + hid_t fapl1 = -1; + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size, new_file_size; + H5FD_mem_t type; + haddr_t addr1, addr2; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0; + htri_t was_extended; + H5FS_stat_t state; + hsize_t alignment=0, mis_align=0, tmp=0, accum=0; + hbool_t have_alloc_vfd; /* Whether VFD used has an 'alloc' callback */ + + TESTING("H5MM_alloc() of file allocation with alignment: test 1"); + + /* Skip test when using VFDs that have their own 'alloc' callback, which + * don't push mis-aligned space fragments on the file free space list + */ + have_alloc_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "stdio") + && HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(have_alloc_vfd) { + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Turn off using meta/small data aggregator */ + if((fapl1 = H5Pcopy(new_fapl)) < 0) TEST_ERROR + + H5Pset_meta_block_size(fapl1, (hsize_t)0); + H5Pset_small_data_block_size(fapl1, (hsize_t)0); + + /* Create the file to work on (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(fapl1, NULL, &alignment) < 0) + TEST_ERROR + + /* Re-open the file with alignment and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl1)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* calculate fragment for alignment of block 30 */ + if((tmp = (hsize_t)file_size % alignment)) + mis_align = alignment - tmp; + + accum = mis_align + TBLOCK_SIZE30; + + /* Allocate a block of 30 from file allocation */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if(addr1 % alignment) TEST_ERROR + + /* there should be nothing in the aggregator */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if(ma_addr || ma_size) TEST_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + if(check_stats(f, f->shared->fs_man[type], &state)) + TEST_ERROR + } + + /* calculate fragment for alignment of block 50 */ + mis_align = 0; + if ((tmp = ((hsize_t)file_size + accum) % alignment)) + mis_align = alignment - tmp; + accum += (mis_align + TBLOCK_SIZE50); + + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if (addr2 % alignment) TEST_ERROR + + /* there should be nothing in the aggregator */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if(ma_addr || ma_size) TEST_ERROR + + if(mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + if(check_stats(f, f->shared->fs_man[type], &state)) + TEST_ERROR + } + + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE50); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + if((new_file_size = h5_get_file_size(filename, fapl1)) < 0) + TEST_ERROR + + if (new_file_size != file_size) + TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support mis-aligned fragments"); + } /* end else */ + + TESTING("H5MF_try_shrink() of file allocation with alignment: test 2"); + + /* Skip test when using VFDs that have their own 'alloc' callback, which + * don't push mis-aligned space fragments on the file free space list + */ + if(have_alloc_vfd) { + /* Re-open the file with alignment and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl1)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* allocate a block of 50 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* address should be aligned */ + if (addr1 % alignment) TEST_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + if((file_size = h5_get_file_size(filename, fapl1)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl1)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* shrink the block */ + if(H5MF_try_shrink(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE50) <= 0) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + if((new_file_size = h5_get_file_size(filename, fapl1)) < 0) + TEST_ERROR + + if (new_file_size != (file_size-TBLOCK_SIZE50)) TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support mis-aligned fragments"); + } /* end else */ + + TESTING("H5MF_try_extend() of file allocation with alignment: test 3"); + + /* Skip test when using VFDs that have their own 'alloc' callback, which + * don't push mis-aligned space fragments on the file free space list + */ + if(have_alloc_vfd) { + /* Re-open the file with alignment and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl1)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* allocate a block of 50 */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* address should be aligned */ + if(addr1 % alignment) TEST_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + if((file_size = h5_get_file_size(filename, fapl1)) < 0) + TEST_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl1)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* try to extend the block */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, type, (haddr_t)addr1, (hsize_t)TBLOCK_SIZE50, (hsize_t)TBLOCK_SIZE30); + + if(was_extended <=0) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + if((new_file_size = h5_get_file_size(filename, fapl1)) < 0) + TEST_ERROR + + if (new_file_size != (file_size+TBLOCK_SIZE30)) TEST_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support mis-aligned fragments"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_eoa() */ + +/* + *------------------------------------------------------------------------- + * To verify that a block allocated from the free-space manager is aligned + * + * Alignment = 1024 or 4096 + * + * Test 1: + * Add section A with an aligned address to free-space manager (addr=alignment, size=50) + * Allocate a block of size=50 + * The returned space's address should be same as section A's address + * + * Test 2: + * Add section A to free-space manager (addr=70, size=8000): + * section A is mis-aligned but the size is big enough for allocation with alignment + * Allocate a block of size=600 + * The returned space should be allocated from section A with an aligned address: + * address=alignment size=600 + * There will be 2 sections in free-space: (alignment = 1024 or alignment = 4096) + * the fragment left from aligning section A: [70, 954] or [70, 4026] + * the section left after allocating block A: [1624, 416] or [4696, 3374] + * H5MF_try_extend() the block of size 600 by 200 should succeed: + * the existing fragment left from aligning section A: [70, 954] or [70, 4026] + * the section left after extending block A: [1824, 216] or [4896, 3174] + * + * Test 3: + * Add section A to free-space manager (addr=70, size=700): + * section A is mis-aligned but the size is not big enough for allocation with alignment + * Allocate a block of size=40 + * The free-space manager is unable to fulfill the request + * The block is allocated from file allocation and should be aligned + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_align_fs(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + h5_stat_size_t file_size; + H5F_t *f = NULL; /* Internal file object pointer */ + H5MF_free_section_t *sect_node = NULL; + haddr_t addr; + H5FS_stat_t state; + htri_t was_extended; + hsize_t alignment=0, tmp=0, mis_align=0; + hbool_t have_alloc_vfd; /* Whether VFD used has an 'alloc' callback */ + + TESTING("H5MF_alloc() of free-space manager with alignment: test 1"); + + /* 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 + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)alignment, (hsize_t)TBLOCK_SIZE50); + + /* Add section A to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += TBLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Allocate a block of 50 */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Verify that the allocated block is section A in free-space */ + if(addr != (haddr_t)alignment) TEST_ERROR + if(addr % alignment) TEST_ERROR + + state.tot_space -= TBLOCK_SIZE50; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Free the block to free-space */ + H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, addr, (hsize_t)TBLOCK_SIZE50); + + state.tot_space += TBLOCK_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("H5MF_alloc() of free-space manager with alignment: test 2"); + + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR70, (hsize_t)TBLOCK_SIZE8000); + + /* Add section A to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += TBLOCK_SIZE8000; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Allocate a block of 600 */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE600); + + /* Verify that the allocated block is aligned */ + if (addr % alignment) TEST_ERROR + + /* should have 1 more section in free-space */ + state.tot_space -= TBLOCK_SIZE600; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* try to extend the block */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_SUPER, (haddr_t)addr, (hsize_t)TBLOCK_SIZE600, (hsize_t)TBLOCK_SIZE200); + + if(was_extended <=0) TEST_ERROR + + /* space should be decreased by 200, # of sections remain the same */ + state.tot_space -= TBLOCK_SIZE200; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + /* Free the block to free-space manager */ + H5MF_xfree(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, addr, (hsize_t)(TBLOCK_SIZE600+TBLOCK_SIZE200)); + + /* only 1 section in free-space because of merging */ + state.tot_space += (TBLOCK_SIZE600+TBLOCK_SIZE200); + state.tot_sect_count = 1; + state.serial_sect_count = 1; + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("H5MF_alloc() of free-space manager with alignment: test 3"); + + /* Skip test when using VFDs that have their own 'alloc' callback, which + * don't push mis-aligned space fragments on the file free space list + */ + have_alloc_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "stdio") + && HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(have_alloc_vfd) { + if((file_size = h5_get_file_size(filename, new_fapl)) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_start_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)H5FD_MEM_SUPER) < 0) + FAIL_STACK_ERROR + + if(f->shared->fs_state[H5FD_MEM_SUPER] != H5F_FS_STATE_OPEN) + TEST_ERROR + if(f->shared->fs_man[H5FD_MEM_SUPER]->client != H5FS_CLIENT_FILE_ID) + TEST_ERROR + + /* Create section A */ + sect_node = H5MF_sect_new(H5MF_FSPACE_SECT_SIMPLE, (haddr_t)TBLOCK_ADDR70, (hsize_t)TBLOCK_SIZE700); + + /* Add section A to free-space manager */ + if(H5MF_add_sect(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, f->shared->fs_man[H5FD_MEM_SUPER], sect_node)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + state.tot_space += TBLOCK_SIZE700; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + /* + * Allocate a block of 40 + * Since free-space manager cannot fulfull the request because of alignment, + * the block is obtained from file allocation + */ + addr = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)(TBLOCK_SIZE40)); + + /* Verify that the allocated block is aligned */ + if(addr % alignment) + TEST_ERROR + + /* verify that the allocated block is from file allocation, not section A in free-space */ + if (!(addr >= (haddr_t)file_size)) TEST_ERROR + + /* calculate fragment for alignment of block 40 from file allocation */ + if ((tmp = (hsize_t)file_size % alignment)) + mis_align = alignment - tmp; + + if (mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + /* free-space info should be the same */ + if(check_stats(f, f->shared->fs_man[H5FD_MEM_SUPER], &state)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support mis-aligned fragments"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_fs() */ + +/* + *------------------------------------------------------------------------- + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 1024 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (nothing in the aggregator) + * request-size > aggr->size and < aggr->alloc_size + * Result: + * An "aggr->alloc_size" block is allocated from file allocation for the aggregator + * EOA is 3072 + * The first block of 30 is allocated from the aggregator and should be aligned + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * There is space of 2018 left in meta_aggr + * + * Allocate second block (50) from meta_aggr: + * (request-size + fragment size) <= aggr->size + * Result: + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[1054, 994] + * There is space of 974 left in meta_aggr + * + * Allocate third block (80) from meta_aggr: + * (request-size + fragment size) > aggr->size + * request-size < meta_aggr->alloc_size + * fragment size < (meta_aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of "meta_aggr->alloc_size" is extended from file allocation for meta_aggr + * EOA is 5120 + * The third block of 80 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[2098, 974] + * There is space of 1968 left in meta_aggr + * + * Allocate fourth block (1970) from meta_aggr: + * (request-size + fragment size) is <= aggr->size + * fragment size > (aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of aggr->alloc_size + fragment size - (aggr->alloc_size - request-size)) + * is extended from file allocation for meta_aggr + * The third block of 1970 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[3152, 944] + * There is space of 1968 left in meta_aggr + * EOA is at 8034 + * + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (aggregator is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A meta_aggr->alloc_size block is allocated from file allocation for the aggregator + * The first block of 30 is allocated from the aggregator and should be aligned + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * There is space of 2018 left in meta_aggr + * EOA is at 6144 + * + * Allocate second block (50) from meta_aggr: + * (request-size + fragment size) is > meta_aggr->size + * request-size < meta_aggr->alloc_size + * fragment size > (meta_aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of meta_aggr->alloc_size + (fragment size - (meta_aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[4126, 4066] + * There is space of 2018 left in meta_aggr + * EOA is at 10260 + * + * Allocate third block (80) from meta_aggr: + * (request-size + fragment size) is > meta_aggr->size + * request-size < meta_aggr->alloc_size + * fragment size > (meta_aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of meta_aggr->alloc_size + (fragment size - (meta_aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * The third block of 80 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[8242, 4046] + * There is space of 2018 left in meta_aggr + * EOA is at 14386 + * + * Allocate fourth block (1970) from meta_aggr: + * (request-size + fragment size) > meta_aggr->size + * request-size < meta_aggr->alloc_size + * fragment size > (meta_aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of meta_aggr->alloc_size + (fragment size - (meta_aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * The fourth block of 1970 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[12368, 4016] + * There is space of 2018 left in meta_aggr + * EOA is at 20372 + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_align_alloc1(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; /* File size */ + + H5FD_mem_t type; + haddr_t addr1, addr2, addr3, addr4; + H5FS_stat_t state; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, mis_align=0; + hsize_t alignment=0, tmp=0; + hbool_t have_alloc_vfd; /* Whether VFD used has an 'alloc' callback */ + + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 1"); + + /* Skip test when using VFDs that have their own 'alloc' callback, which + * don't push mis-aligned space fragments on the file free space list + */ + have_alloc_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "stdio") + && HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(have_alloc_vfd) { + /* 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 (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* calculate fragment for alignment of block 30 */ + if((tmp = (hsize_t)file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if(addr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 is freed to free-space */ + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + if(mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if ((addr1 + TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 50 */ + mis_align = 0; + if((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 50 from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if(addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 50 is freed to free-space */ + if(mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr2 + TBLOCK_SIZE50) != ma_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 80 */ + mis_align = 0; + if ((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE80); + + /* Verify that the allocated block is aligned */ + if(addr3 % alignment) TEST_ERROR + + /* fragment for alignment of block 80 is freed to free-space */ + if(mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr3 + TBLOCK_SIZE80) != ma_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 1970 */ + mis_align = 0; + if((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 1970 from meta_aggr */ + addr4 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1970); + + /* Verify that the allocated block is aligned */ + if(addr4 % alignment) TEST_ERROR + + /* fragment for alignment of block 1970 is freed to free-space */ + if(mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr4 + TBLOCK_SIZE1970) != ma_addr) + TEST_ERROR + + /* Verify total size of free space after all the allocations */ + if(check_stats(f, f->shared->fs_man[type], &state)) + TEST_ERROR + + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE50); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE80); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE1970); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support mis-aligned fragments"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc1() */ + +/* + *------------------------------------------------------------------------- + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 1024 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A meta_aggr->alloc_size block is allocated from file allocation for the aggregator + * The first block of 30 is allocated from the aggregator and should be aligned + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * There is space of 2018 left in meta_aggr + * EOA is 3072 + * + * Allocate second block (50) from meta_aggr: + * (request-size+fragment size) <= aggr->size + * Result: + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[1054, 994] + * There is space of 974 left in meta_aggr + * + * Allocate first block (30) from sdata_aggr: (sdata_aggr is empty) + * request-size is > sdata_aggr->size and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is obtained via file allocation + * The first block of 30 is allocated from sdata_aggr and should be aligned + * EOA is 5120 + * + * Allocate third block (80) from meta_aggr: + * request-size+fragment size is > meta_aggr->size + * sdata_aggr is at EOA but has not used up more than sdata_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * The unused space in meta_aggr is freed to free-space [2098, 974] + * meta_aggr is updated to point to the new block + * The third block of 80 is allocated from meta_aggr and should be aligned + * EOA is 7168 + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > aggr->size and < aggr->alloc_size + * Result: + * A meta_aggr->alloc_size block is allocated from file allocation for the aggregator + * The first block of 30 is allocated from the aggregator and should be aligned + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * There is space of 2018 left meta_aggr + * EOA is at 6144 + * + * Allocate second block (50) from meta_aggr: + * (request-size + fragment size) > aggr->size + * request-size < aggr->alloc_size + * fragment size > (aggr->alloc_size - request-size) + * Result: + * A block of (fragment size + request-size) is extended from file allocation for the aggregator + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[4126, 4066] + * There is space of 2018 left in meta_aggr + * EOA is at 10260 + * + * Allocate first block (30) from sdata_aggr: (sdata_aggr is empty) + * request-size is > sdata_aggr->size and < sdata_aggr->alloc_size + * meta_aggr is at EOA and has used up more than meta_aggr->alloc_size + * Result: + * The remaining space in meta_aggr is freed to free-space [8242, 2018] and shrunk since at EOF + * meta_aggr is reset to 0 + * A block of sdata_aggr->alloc_size is obtained via file allocation + * Fragment from alignment of file allocation is freed to free-space: [8242, 4046] + * The first block of 30 is allocated from sdata_aggr and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 14336 + * + * Allocate third block (80) from meta_aggr: + * (request-size + fragment size) is > meta_aggr->size + * request-size < meta_aggr->alloc_size + * sdata_aggr is at EOA but has not used up more than sdata_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation for the aggregator + * Fragment from alignment of file allocation is freed to free-space:[14336, 2048] + * other_aggr is [12318, 2018] + * The third block of 80 is allocated from the aggregator and should be aligned + * There is space of 1968 left in meta_aggr + * EOA is at 18432 + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_align_alloc2(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; /* File size */ + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3, saddr1; + H5FS_stat_t state[H5FD_MEM_NTYPES]; + haddr_t ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, sdata_size=0, mis_align=0; + hsize_t alignment=0, tmp=0; + hbool_t have_alloc_vfd; /* Whether VFD used has an 'alloc' callback */ + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 2"); + + /* Skip test when using VFDs that have their own 'alloc' callback, which + * don't push mis-aligned space fragments on the file free space list + */ + have_alloc_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "stdio") + && HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(have_alloc_vfd) { + /* 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 (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* calculate fragment for alignment of block 30 */ + if((tmp = (hsize_t)file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if(addr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 is freed to free-space */ + HDmemset(&state, 0, sizeof(H5FS_stat_t) * H5FD_MEM_NTYPES); + if(mis_align) { + state[type].tot_space += mis_align; + state[type].tot_sect_count += 1; + state[type].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr1 + TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* fragment for alignment of block 50 is freed to free-space */ + mis_align = 0; + if((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if(addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 50 is freed to free-space */ + if(mis_align) { + state[type].tot_space += mis_align; + state[type].tot_sect_count += 1; + state[type].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr2 + TBLOCK_SIZE50) != ma_addr) + TEST_ERROR + + /* + * Calculate fragment for alignment of block 30 in sdata_aggr: + * + * For alignment = 1024, alloc_size = 2048: + * block 30 is allocated from (ma_addr + ma_size), + * which is already aligned + * + * For alignment = 4096, alloc_size = 2048: + * since remaining space in meta_aggr is freed and shrunk, + * block 30 is allocated from ma_addr + */ + mis_align = 0; + if((alignment == TEST_ALIGN1024) && (tmp = ((ma_addr + ma_size) % alignment))) + mis_align = alignment - tmp; + else if ((alignment == TEST_ALIGN4096) && (tmp = (ma_addr % alignment))) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* fragment for alignment of block 30 for sdata_aggr is freed to free-space */ + if(mis_align) { + state[stype].tot_space += mis_align; + state[stype].tot_sect_count += 1; + state[stype].serial_sect_count += 1; + } + + /* Verify that the allocated block is aligned */ + if (saddr1 % alignment) TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if(sdata_addr != (saddr1 + TBLOCK_SIZE30)) TEST_ERROR + + /* + * Calculate fragment for the allocation of block 80 from meta_aggr: + * + * For alignment = 1024, alloc_size = 2048: + * fragment for unused space in meta_aggr is freed to free-space + * For alignment = 4096, alloc_size = 2048: + * fragment from alignment of ma_addr is freed + * block 30 is allocated from ma_addr + */ + mis_align = 0; + if((alignment == TEST_ALIGN1024) && (tmp = (ma_addr % alignment))) + mis_align = alignment - tmp; + else if ((alignment == TEST_ALIGN4096) && (tmp = ((sdata_addr + sdata_size) % alignment))) + mis_align = alignment - tmp; + + /* Allocate a block of 80 from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE80); + + /* Verify that the allocated block is aligned */ + if (addr3 % alignment) TEST_ERROR + + /* fragment for alignment of block 80 is freed to free-space */ + if(mis_align) { + state[type].tot_space += mis_align; + state[type].tot_sect_count += 1; + state[type].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr3 + TBLOCK_SIZE80) != ma_addr) + TEST_ERROR + + /* Verify total size of free space after all the allocations */ + if(f->shared->fs_man[type]) { + if(check_stats(f, f->shared->fs_man[type], &(state[type]))) + TEST_ERROR + } + + if(f->shared->fs_man[stype]) { + if(check_stats(f, f->shared->fs_man[stype], &(state[stype]))) + TEST_ERROR + } + + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE50); + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE80); + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE30); + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support mis-aligned fragments"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc2() */ + +/* + *------------------------------------------------------------------------- + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 1024 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation for the aggregator + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 3072 + * + * Allocate second block (50) from meta_aggr: + * (request-size+fragment size) is <= aggr->size + * Result: + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[1054, 994] + * There is space of 974 left in the aggregator + * + * Allocate first block (30) from other_aggr: (nothing in other_aggr) + * request-size is > what is left in other_aggr->size and < other_aggr->alloc_size + * Result: + * A "other_aggr->alloc_size" block is allocated from file allocation for other_aggr + * The first block of 30 is allocated from other_aggr and should be aligned + * There is space of 2018 left in other_aggr->size + * EOA is 5120 + * + * Allocate second block (50) from sdata_aggr: + * (request-size+fragment size) < sdata_aggr->size + * Result: + * The second block of 50 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[3102, 994] + * There is space of 974 left in sdata_aggr + * + * Allocate third block (80) from sdata_aggr: + * (request-size+fragment size) is >= sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * sdata_aggr is at EOA + * Result: + * Another block of sdata_aggr->alloc_size is extended from file allocation for sdata_aggr + * The third block of 80 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[4146, 974] + * There is space of 1968 left in sdata_aggr + * EOA is 7168 + * + * Allocate third block (1034) from meta_aggregator: + * (request-size + alignment) > meta_aggr->size but < meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * The unused space in sdata_aggr is freed to free-space [5200, 1968] then shrunk + * sdata_aggr is reset to 0 + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space [5200, 944] + * The unused space in meta_aggr is freed to free-space [2098, 974] + * The meta_aggr is updated to point to the new space + * The block of 1034 is allocated from the new block and should be aligned + * There is space of 1014 left in meta_aggr + * EOA is 8192 + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > what is left in aggr->size and < aggr->alloc_size + * Result: + * A meta_aggr->alloc block is allocated from file allocation for the aggregator + * The first block of 30 is allocated from the aggregator and should be aligned + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * There is space of 2018 left in meta_aggr + * EOA is at 6144 + * + * Allocate second block (50) from meta_aggr: + * (request-size + fragment size) is > what is left in aggr->size + * request-size < aggr->alloc_size + * fragment size > (aggr->alloc_size - request-size) + * Result: + * A block of aggr->alloc_size + (fragment size - (aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * The second block of 50 is allocated from the aggregator and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[4126, 4066] + * There is space of 2018 left in meta_aggr + * EOA is at 10260 + * + * Allocate first block (30) from sdata_aggr: (sdata_aggr is empty) + * request-size > sdata_aggr->size and < sdata_aggr->alloc_size + * meta_aggr is at EOA and has used up more than meta_aggr->alloc_size + * Result: + * The remaining space in meta_aggr is freed to free-space [8242, 2018] and shrunk + * since at EOF + * meta_aggr is reset to 0 + * A block of sdata_aggr->alloc_size is obtained via file allocation + * Fragment from alignment of file allocation is freed to free-space: [8242, 4046] + * The first block of 30 is allocated from sdata_aggr and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 14336 + * + * Allocate second block (50) from sdata_aggr: + * request-size is > sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * fragment size > (sdata_aggr->alloc_size - request-size) + * Result: + * A block of sdata_aggr->alloc_size + (fragment size - (sdata_aggr->alloc_size - request-size)) + * is extended from file allocation for the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[12318, 4066] + * The second block of 50 is allocated from the aggregator and should be aligned + * There is space of 2018 left in the sdata_aggr + * EOA is at 18452 + * + * Allocate third block (80) from sdata_aggr: + * request-size + fragment size is > sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * fragment size > (sdata_aggr->alloc_size - request-size) + * Result: + * A block of sdata_aggr->alloc_size + (fragment size - (sdata_aggr->alloc_size - request-size) + * is allocated from file allocation for the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[16434, 4046] + * The third block of 80 is allocated from the aggregator and should be aligned + * There is space of 2018 left in the sdata_aggr + * EOA is at 22578 + * + * Allocate third block (1034) from meta_aggregator: + * (request-size + fragment size) is > meta_aggr->size but request-size < meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * The remaining space in sdata_aggr is freed to free-space [20560, 2018] then shrunk + * sdata_aggr is reset to 0 + * There is nothing in meta_aggr + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space [20560, 4016] + * EOA is 26624 + * The meta_aggr is updated to point to the new space + * The block of 1034 is allocated from the new block and should be aligned + * There is space of 1014 left in meta_aggr + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_align_alloc3(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; + H5FD_mem_t type, stype; + haddr_t addr1, addr2, addr3; + haddr_t saddr1, saddr2, saddr3; + H5FS_stat_t state[H5FD_MEM_NTYPES]; + haddr_t ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, sdata_size=0, mis_align=0; + hsize_t alignment=0, tmp=0; + hbool_t have_alloc_vfd; /* Whether VFD used has an 'alloc' callback */ + + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 3"); + + /* Skip test when using VFDs that have their own 'alloc' callback, which + * don't push mis-aligned space fragments on the file free space list + */ + have_alloc_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "stdio") + && HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(have_alloc_vfd) { + /* 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 (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* calculate fragment for alignment of block 30 */ + if((tmp = (hsize_t)file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if(addr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 is freed to free-space */ + HDmemset(&state, 0, sizeof(H5FS_stat_t) * H5FD_MEM_NTYPES); + if(mis_align) { + state[type].tot_space += mis_align; + state[type].tot_sect_count += 1; + state[type].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1 + TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 50 */ + mis_align = 0; + if((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 50 from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if(addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 50 is freed to free-space */ + if(mis_align) { + state[type].tot_space += mis_align; + state[type].tot_sect_count += 1; + state[type].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if((addr2 + TBLOCK_SIZE50) != ma_addr) + TEST_ERROR + + /* + * Calculate fragment for alignment of block 30 in sdata_aggr: + * + * For alignment = 1024, alloc_size = 2048: + * block 30 is allocated from (ma_addr + ma_size), + * which is already aligned + * + * For alignment = 4096, alloc_size = 2048: + * since remaining space in meta_aggr is freed and shrunk, + * block 30 is allocated from ma_addr + */ + mis_align = 0; + if((alignment == TEST_ALIGN1024) && (tmp = ((ma_addr + ma_size) % alignment))) + mis_align = alignment - tmp; + else if ((alignment == TEST_ALIGN4096) && (tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if(saddr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 for sdata_aggr is freed to free-space */ + if(mis_align) { + state[stype].tot_space += mis_align; + state[stype].tot_sect_count += 1; + state[stype].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if(sdata_addr != (saddr1+TBLOCK_SIZE30)) TEST_ERROR + + /* calculate fragment for alignment of block 50 in sdata_aggr */ + mis_align = 0; + if((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 50 from sdata_aggr */ + saddr2 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if(saddr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 50 for sdata_aggr is freed to free-space */ + if(mis_align) { + state[stype].tot_space += mis_align; + state[stype].tot_sect_count += 1; + state[stype].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if(sdata_addr != (saddr2 + TBLOCK_SIZE50)) TEST_ERROR + + /* calculate fragment for alignment of block 80 in sdata_aggr */ + mis_align = 0; + if((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 80 from sdata_aggr */ + saddr3 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE80); + + /* Verify that the allocated block is aligned */ + if(saddr3 % alignment) TEST_ERROR + + /* fragment for alignment of block 80 for sdata_aggr is freed to free-space */ + if(mis_align) { + state[stype].tot_space += mis_align; + state[stype].tot_sect_count += 1; + state[stype].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if ((saddr3 + TBLOCK_SIZE80) != sdata_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 1034 */ + mis_align = 0; + if((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 1034 for meta_aggr */ + addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1034); + + /* Verify that the allocated block is aligned */ + if(addr3 % alignment) TEST_ERROR + + /* fragment for alignment of block 1034 for meta_aggr is freed to free-space */ + if(mis_align) { + state[type].tot_space += mis_align; + state[type].tot_sect_count += 1; + state[type].serial_sect_count += 1; + } + + /* calculate unused space in meta_aggr that is freed to free-space after block 1034 */ + mis_align = 0; + if((alignment == TEST_ALIGN1024) && (tmp = (ma_addr % alignment))) + mis_align = alignment - tmp; + + /* fragment for unused space in meta_aggr after block 1034 is freed to free-space */ + if(mis_align) { + state[type].tot_space += mis_align; + state[type].tot_sect_count += 1; + state[type].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr3 + TBLOCK_SIZE1034) != ma_addr) + TEST_ERROR + + /* Verify total size of free space after all allocations */ + if(f->shared->fs_man[type]) { + if(check_stats(f, f->shared->fs_man[type], &(state[type]))) + TEST_ERROR + } + + if(f->shared->fs_man[stype]) { + if(check_stats(f, f->shared->fs_man[stype], &(state[stype]))) + TEST_ERROR + } + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support mis-aligned fragments"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc3() */ + + +/* + *------------------------------------------------------------------------- + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * The first block of 30 is allocated from meta_aggr and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 3072 + * + * Allocate second block (2058) from meta_aggr: + * (request-size+fragment) is > meta_aggr->size and request-size is > meta_aggr->alloc_size + * meta_aggr is at EOA + * Result: + * The second block of 2058 + fragment is extended and merged together with meta_aggr + * The block of 2058 is allocated out of the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[1054, 994] + * There is space of 2018 (same as before) left in meta_aggr + * EOA is 6124 + * + * Allocate third block (5) from meta_aggr: + * request-size+fragment < meta_aggr->size + * Result: + * A block of 5 is allocated from the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[4106, 1014] + * There is space of 999 left in meta_aggr + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * The first block of 30 is allocated from meta_aggr and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 6144 + * + * Allocate second block (2058) from meta_aggr: + * (request-size+fragment) is > meta_aggr->size and request-size is > meta_aggr->alloc_size + * meta_aggr is at EOA + * Result: + * The second block of 2058 + fragment is extended and merged together with meta_aggr + * The block of 2058 is allocated out of the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[4126, 4066] + * There is space of 2018 (same as before) left in meta_aggr + * EOA is 12268 + * + * Allocate third block (5) from meta_aggr: + * request-size+fragment is > meta_aggr->size + * request-size < meta_aggr->alloc_size + * fragment < (meta_aggr->alloc_size - request-size) + * meta_aggr is at EOA + * Result: + * A block of meta_aggr->alloc_size is extended from file allocation for the aggregator + * A block of 5 is allocated from the aggregator + * Fragment from alignment of aggregator allocation is freed to free-space:[10250, 2038] + * There is space of 2023 left in meta_aggr + * + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_align_alloc4(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; + H5FD_mem_t type; + haddr_t addr1, addr2, addr3; + H5FS_stat_t state; + haddr_t ma_addr=HADDR_UNDEF; + hsize_t ma_size=0, saved_ma_size=0; + hsize_t alignment=0, mis_align=0, tmp=0; + hbool_t have_alloc_vfd; /* Whether VFD used has an 'alloc' callback */ + + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 4"); + + /* Skip test when using VFDs that have their own 'alloc' callback, which + * don't push mis-aligned space fragments on the file free space list + */ + have_alloc_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "stdio") + && HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(have_alloc_vfd) { + /* 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 (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* calculate fragment for alignment of block 30 */ + if((tmp = (hsize_t)file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if(addr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 is freed to free-space */ + HDmemset(&state, 0, sizeof(H5FS_stat_t)); + if(mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + saved_ma_size = ma_size; + if((addr1+TBLOCK_SIZE30) != ma_addr) TEST_ERROR + + /* calculate fragment for alignment of block 2058 */ + mis_align = 0; + if((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 2058 from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2058); + + /* Verify that the allocated block is aligned */ + if(addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 2058 is freed to free-space */ + if(mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr2 + TBLOCK_SIZE2058) != ma_addr) TEST_ERROR + + /* meta_aggr->size remains the same */ + if(ma_size != saved_ma_size) TEST_ERROR + + /* calculate fragment for alignment of block 5 from meta_aggr */ + mis_align = 0; + if((tmp = ma_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 5 from meta_aggr */ + addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5); + + /* fragment for alignment of block 5 is freed to free-space */ + if(mis_align) { + state.tot_space += mis_align; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + } + + /* Verify that the allocated block is aligned */ + if(addr3 % alignment) TEST_ERROR + + /* Verify total size of free space after all allocations */ + if(f->shared->fs_man[type]) { + if(check_stats(f, f->shared->fs_man[type], &state)) + TEST_ERROR + } + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support mis-aligned fragments"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc4() */ + +/* + *------------------------------------------------------------------------- + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 1024 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * The first block of 30 is allocated from meta_aggr and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 3072 + * + * Allocate first block (30) from sdata_aggr: (nothing in the aggregator) + * A block of sdata_aggr->alloc_size is allocated from file allocation + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 5120 + * + * Allocate second block (2058) from meta_aggr: + * (request-size + fragment size) > meta_aggr->size and > meta_aggr->alloc_size + * sdata_aggr is at EOA but has not used up sdata_aggr->alloc_size + * Result: + * A block of 2058 is allocated from file allocation + * EOA is 7178 + * Nothing is changed in meta_aggr and sdata_aggr + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * The first block of 30 is allocated from meta_aggr and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 6144 + * + * Allocate first block (30) from sdata_aggr: (meta_aggr is empty) + * meta_aggr is at EOA but has not used up more than meta_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[6144, 2048] + * This fragment adjoins meta_aggr and fulfills "absorb" condition, + * the remaining space left in meta_aggr is absorbed into the fragment and + * freed to free-space: [4126, 2018] + * meta_aggr is reset to 0 + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 10240 + * + * Allocate second block (2058) from meta_aggr: + * request-size + fragment size is > meta_aggr->size + * request_size is > meta_aggr->alloc_size + * sdata_aggr is at EOA but has not used up more than sdata_aggr->alloc_size + * Result: + * A block of 2058 is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[10240, 2048] + * This fragment adjoins sdata_aggr and fulfills "absorb" condition, + * the remaining space left in sdata_aggr is absorbed into the fragment and + * freed to free-space: [8222, 2018] + * sdata_aggr is reset to 0 + * EOA is 14346 + * meta_aggr and sdata_aggr are all 0 + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_align_alloc5(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; + H5FD_mem_t type, stype; + haddr_t addr1, addr2, saddr1; + H5FS_stat_t state[H5FD_MEM_NTYPES]; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF; + haddr_t sdata_addr=HADDR_UNDEF, new_sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0, sdata_size=0, new_sdata_size=0; + hsize_t alignment=0, mis_align=0, tmp=0; + hbool_t have_alloc_vfd; /* Whether VFD used has an 'alloc' callback */ + + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 5"); + + /* Skip test when using VFDs that have their own 'alloc' callback, which + * don't push mis-aligned space fragments on the file free space list + */ + have_alloc_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "stdio") + && HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(have_alloc_vfd) { + /* 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 (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* calculate fragment for alignment of block 30 */ + if((tmp = (hsize_t)file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if(addr1 % alignment) TEST_ERROR + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + + if((addr1 + TBLOCK_SIZE30) != ma_addr) TEST_ERROR + + /* fragment for alignment of block 30 is freed to free-space */ + HDmemset(&state, 0, sizeof(H5FS_stat_t) * H5FD_MEM_NTYPES); + if(mis_align) { + state[type].tot_space += mis_align; + state[type].tot_sect_count += 1; + state[type].serial_sect_count += 1; + } + + /* calculate fragment for alignment of block 30 from sdata_aggr */ + mis_align = 0; + if((tmp = (ma_addr + ma_size) % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if(saddr1 % alignment) TEST_ERROR + + /* fragment of alignment for block 30 in sdata_aggr is freed to free-space */ + if(mis_align) { + state[stype].tot_space += mis_align; + state[stype].tot_sect_count += 1; + state[stype].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if((saddr1+TBLOCK_SIZE30) != sdata_addr) TEST_ERROR + + /* calculate fragment for alignment of block 2058 from meta_aggr */ + mis_align = 0; + if((tmp = (sdata_addr + sdata_size) % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 2058 from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2058); + + /* Verify that the allocated block is aligned */ + if (addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 2058 is freed to free-space */ + if(mis_align) { + state[type].tot_space += mis_align; + state[type].tot_sect_count += 1; + state[type].serial_sect_count += 1; + } + + /* Verify total size of free space after all allocations */ + if(f->shared->fs_man[type]) { + if(check_stats(f, f->shared->fs_man[type], &(state[type]))) + TEST_ERROR + } + + if(f->shared->fs_man[stype]) { + if(check_stats(f, f->shared->fs_man[stype], &(state[stype]))) + TEST_ERROR + } + + /* nothing is changed in meta_aggr */ + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + if (new_ma_addr != ma_addr || new_ma_size != ma_size) + TEST_ERROR + + /* nothing is changed in sdata_aggr */ + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &new_sdata_addr, &new_sdata_size); + if (new_sdata_addr != sdata_addr || new_sdata_size != sdata_size) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support mis-aligned fragments"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc5() */ + + +/* + *------------------------------------------------------------------------- + * To verify that blocks allocated from the aggregator are aligned + * + * Alignment = 1024 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is empty) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 224] + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in meta_aggr->size + * EOA is 3072 + * + * Allocate first block (30) from sdata_aggr: (sdata_aggr is empty) + * request_size > sdata_aggr->size and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is allocated from file allocation + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 5120 + * + * Allocate second block (50) from sdata_aggr: + * (request-size+fragment size) <= sdata_aggr->size + * Result: + * The second block of 50 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[3102, 994] + * There is space of 974 left in sdata_aggr + * + * Allocate third block (80) from sdata_aggr: + * (request-size+fragment size) > sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * fragment size < (sdata_aggr->alloc_size - request-size) + * Result: + * Another block of sdata_aggr->alloc_size block is extended from file allocation + * for sdata_aggr + * The third block of 80 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[4146, 974] + * There is space of 1968 left in sdata_aggr + * EOA is 7168 + * + * Allocate second block (2058) from meta_aggr: + * request-size + fragment size is > meta_aggr->size + * request-size is > meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * The remaining space in sdata_aggr is freed to free-space and shrunk + * sdata_aggr is reset to 0 + * A block of 2058 is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[5200, 944] + * EOA is at 8202 + * meta_aggr is unchanged + * + * Alignment = 4096 aggr->alloc_size = 2048 + * + * Allocate first block (30) from meta_aggr: (meta_aggr is emtpy) + * request-size is > meta_aggr->size and < meta_aggr->alloc_size + * Result: + * A block of meta_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[800, 3296] + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in meta_aggr + * EOA is 6144 + * + * Allocate first block (30) from sdata_aggr: (sdata_aggr is empty) + * request_size > sdata_aggr->size and < sdata_aggr->alloc_size + * Result: + * A block of sdata_aggr->alloc_size is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space: [6144, 2048] + * The first block of 30 is allocated from the aggregator and should be aligned + * There is space of 2018 left in sdata_aggr + * EOA is 10240 + * + * Allocate second block (50) from sdata_aggr: + * (request-size+fragment size) is > sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * fragment size > (sdata_aggr->alloc_size - request-size) + * Result: + * A block of (fragment size + request-size) is extended from file allocation for the aggregator + * The second block of 50 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[8222, 4066] + * There is space of 2018 left in sdata_aggr + * EOA is at 14356 + * + * Allocate third block (80) from sdata_aggr: + * (request-size+fragment size) is > sdata_aggr->size + * request-size < sdata_aggr->alloc_size + * fragment size > (sdata_aggr->alloc_size - request-size) + * Result: + * A block of (fragment size + request-size) is extended from file allocation for sdata_aggr + * The third block of 80 is allocated from sdata_aggr and should be aligned + * Fragment from alignment of aggregator allocation is freed to free-space:[12338, 4046] + * There is space of 2018 left in sdata_aggr + * EOA is 18482 + * + * Allocate second block (2058) from meta_aggr: + * request-size + fragment size is > meta_aggr->size + * request-size is > meta_aggr->alloc_size + * sdata_aggr is at EOA and has used up more than sdata_aggr->alloc_size + * Result: + * The remaining space in sdata_aggr is freed to free-space and shrunk: [16464, 2018] + * sdata_aggr is reset to 0 + * A block of 2058 is allocated from file allocation + * Fragment from alignment of file allocation is freed to free-space:[16464, 4016] + * EOA is at 22538 + * meta_aggr is unchanged + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_align_alloc6(const char *env_h5_drvr, hid_t fapl, hid_t new_fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + h5_stat_size_t file_size; + H5FD_mem_t type, stype; + haddr_t addr1, addr2; + haddr_t saddr1, saddr2, saddr3; + H5FS_stat_t state[H5FD_MEM_NTYPES]; + haddr_t ma_addr=HADDR_UNDEF, new_ma_addr=HADDR_UNDEF, sdata_addr=HADDR_UNDEF; + hsize_t ma_size=0, new_ma_size=0, sdata_size=0; + hsize_t alignment=0, mis_align=0, tmp=0; + hbool_t have_alloc_vfd; /* Whether VFD used has an 'alloc' callback */ + + TESTING("H5MF_alloc() of meta/sdata aggregator with alignment: test 6"); + + /* Skip test when using VFDs that have their own 'alloc' callback, which + * don't push mis-aligned space fragments on the file free space list + */ + have_alloc_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "stdio") + && HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + if(have_alloc_vfd) { + /* 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 (without alignment) */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Re-open the file with alignment setting and meta/sdata setting */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, new_fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* get alignment setting */ + if(H5Pget_alignment(new_fapl, NULL, &alignment) < 0) + TEST_ERROR + + /* calculate fragment for alignment of block 30 */ + if((tmp = (hsize_t)file_size % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from meta_aggr */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (addr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 in meta_aggr is freed to free-space */ + HDmemset(&state, 0, sizeof(H5FS_stat_t) * H5FD_MEM_NTYPES); + if(mis_align) { + state[type].tot_space += mis_align; + state[type].tot_sect_count += 1; + state[type].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size); + if ((addr1+TBLOCK_SIZE30) != ma_addr) + TEST_ERROR + + /* calculate fragment for alignment of block 30 in sdata_aggr */ + mis_align = 0; + if ((tmp = (ma_addr + ma_size) % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 30 from sdata_aggr */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that the allocated block is aligned */ + if (saddr1 % alignment) TEST_ERROR + + /* fragment for alignment of block 30 in sdata_aggr is freed to free-space */ + if (mis_align) { + state[stype].tot_space += mis_align; + state[stype].tot_sect_count += 1; + state[stype].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if (sdata_addr != (saddr1+TBLOCK_SIZE30)) TEST_ERROR + + /* calculate fragment for alignment of block 50 in sdata_aggr */ + mis_align = 0; + if ((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 50 from sdata_aggr */ + saddr2 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Verify that the allocated block is aligned */ + if (saddr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 50 in sdata_aggr is freed to free-space */ + if (mis_align) { + state[stype].tot_space += mis_align; + state[stype].tot_sect_count += 1; + state[stype].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if (sdata_addr != (saddr2+TBLOCK_SIZE50)) TEST_ERROR + + /* calculate fragment for alignment of block 80 in sdata_aggr */ + mis_align = 0; + if ((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 80 from sdata_aggr */ + saddr3 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE80); + + /* Verify that the allocated block is aligned */ + if (saddr3 % alignment) TEST_ERROR + + /* fragment for alignment of block 80 in sdata_aggr is freed to free-space */ + if (mis_align) { + state[stype].tot_space += mis_align; + state[stype].tot_sect_count += 1; + state[stype].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + if (sdata_addr != (saddr3+TBLOCK_SIZE80)) TEST_ERROR + + /* calculate fragment for alignment of block 2058 */ + /* remaining space in sdata_aggr is freed and shrunk */ + mis_align = 0; + if ((tmp = sdata_addr % alignment)) + mis_align = alignment - tmp; + + /* Allocate a block of 2058 from meta_aggr */ + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2058); + + /* Verify that the allocated block is aligned */ + if (addr2 % alignment) TEST_ERROR + + /* fragment for alignment of block 2058 is freed to free-space */ + if (mis_align) { + state[type].tot_space += mis_align; + state[type].tot_sect_count += 1; + state[type].serial_sect_count += 1; + } + + H5MF_aggr_query(f, &(f->shared->meta_aggr), &new_ma_addr, &new_ma_size); + H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sdata_addr, &sdata_size); + + if (new_ma_addr != ma_addr && new_ma_size != ma_size) + TEST_ERROR + + if (sdata_addr != HADDR_UNDEF || sdata_size != 0) + TEST_ERROR + + if(f->shared->fs_man[type]) { + if(check_stats(f, f->shared->fs_man[type], &(state[type]))) + TEST_ERROR + } + + + if(f->shared->fs_man[stype]) { + if(check_stats(f, f->shared->fs_man[stype], &(state[stype]))) + TEST_ERROR + } + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + } /* end if */ + else { + SKIPPED(); + puts(" Current VFD doesn't support mis-aligned fragments"); + } /* end else */ + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_align_alloc6() */ + +/* + * Test a bug that occurs when an allocator with zero size left and an unaligned + * endpoint is extended to allocate an aligned object + */ +static unsigned +test_mf_bug1(const char *env_h5_drvr, hid_t fapl) +{ + hid_t file = -1; /* File ID */ + hid_t copied_fapl = -1; /* FAPL to use for this test */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FD_mem_t type; + haddr_t addr1, addr2; + hsize_t block_size; + hsize_t align; + hbool_t split = FALSE, multi = FALSE; + + TESTING("H5MF_alloc() bug 1"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Copy fapl */ + if((copied_fapl = H5Pcopy(fapl)) < 0) + TEST_ERROR + + /* Get metadata block size */ + if(H5Pget_meta_block_size(copied_fapl, &block_size) < 0) + TEST_ERROR + + /* Set alignment to equal block size / 2 */ + align = block_size / 2; + if(H5Pset_alignment(copied_fapl, 0, align) < 0) + TEST_ERROR + + /* Check for split or multi driver */ + if(!HDstrcmp(env_h5_drvr, "split")) + split = TRUE; + else if(!HDstrcmp(env_h5_drvr, "multi")) + multi = TRUE; + + /* Add alignment to member files for split/multi driver */ + if(split || multi) { + hid_t memb_fapl; + + /* Creat fapl */ + if((memb_fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) + TEST_ERROR + + /* Set alignment. Note that it is the block size of the parent FAPL that + * is important here. */ + if(H5Pset_alignment(memb_fapl, 0, align) < 0) + TEST_ERROR + + if(split) { + /* Set split driver with new FAPLs */ + if(H5Pset_fapl_split(copied_fapl, "-m.h5", memb_fapl, "-r.h5", memb_fapl) < 0) + TEST_ERROR + } /* end if */ + else { + H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; + hid_t memb_fapl_arr[H5FD_MEM_NTYPES]; + char *memb_name[H5FD_MEM_NTYPES]; + haddr_t memb_addr[H5FD_MEM_NTYPES]; + hbool_t relax; + H5FD_mem_t mt; + + /* Get current multi settings */ + HDmemset(memb_name, 0, sizeof memb_name); + if(H5Pget_fapl_multi(copied_fapl, memb_map, NULL, memb_name, memb_addr, &relax) < 0) + TEST_ERROR + + /* Populate memb_fapl_arr, patch memb_addr so member file addresses + * are aligned */ + for(mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, mt)) { + memb_fapl_arr[mt] = memb_fapl; + memb_addr[mt] = ((memb_addr[mt] + align - 1) / align) * align; + } /* end for */ + + /* Set multi driver with new FAPLs */ + if(H5Pset_fapl_multi(copied_fapl, memb_map, memb_fapl_arr, (const char * const *)memb_name, memb_addr, relax) < 0) + TEST_ERROR + + /* Free memb_name */ + for(mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, mt)) + free(memb_name[mt]); + } /* end else */ + + /* Close memb_fapl */ + if(H5Pclose(memb_fapl) < 0) + TEST_ERROR + } /* end if */ + + /* Reopen the file with alignment */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, copied_fapl)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + TEST_ERROR + + /* Allocate a block of size align from meta_aggr. This should create an + * aggregator that extends to the end of the file, with + * block_size / 2 bytes remaining, and the end of the file aligned */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, align); + + /* Verify that the allocated block is aligned */ + if(addr1 % align) TEST_ERROR + + /* Allocate a block of size align from meta_aggr. This should force the + * aggregator to extend to the end of the file, with 0 bytes remaining, and + * the end of the file aligned */ + type = H5FD_MEM_SUPER; + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, align); + + /* Verify that the allocated block is aligned */ + if(addr2 % align) TEST_ERROR + + /* Verify that the allocated block is placed align after the previous */ + if((addr2 - addr1) != align) TEST_ERROR + + /* Allocate a block of size block_size + 1 from meta_aggr. This should + * force the aggregator to extend to the end of the file, with 0 bytes + * remaining, and the end of the file unaligned */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, block_size + (hsize_t)1); + + /* Verify that the allocated block is aligned */ + if(addr1 % align) TEST_ERROR + + /* Verify that the allocated block is placed block_size / 2 after the + * previous */ + if((addr1 - addr2) != align) TEST_ERROR + + /* Allocate a block of size 1. This should extend the aggregator from + * the previous allocation, and align the new block */ + type = H5FD_MEM_SUPER; + addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)1); + + /* Verify that the allocated block is aligned */ + if(addr2 % align) TEST_ERROR + + /* Verify that the allocated block is placed 3 * (block_size / 2) after + * the previous */ + if((addr2 - addr1) != (3 * align)) TEST_ERROR + + PASSED() + + /* Close file */ + if(H5Fclose(file) < 0) + TEST_ERROR + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_bug1() */ + +/* + * Verify that the file's free-space manager(s) are persistent for a split-file + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_fs_persist_split(void) +{ + hid_t file = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list ID */ + hid_t fapl = -1; /* File access property list ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FD_mem_t type, stype, btype; /* File allocation type */ + H5FS_stat_t fs_stat; /* Information for free-space manager */ + haddr_t addr1, addr2, addr3, addr4; /* File address for H5FD_MEM_SUPER */ + haddr_t saddr1, saddr2, saddr3, saddr4; /* File address for H5FD_MEM_DRAW */ + haddr_t baddr5, baddr6, baddr7, baddr8; /* File address for H5FD_MEM_BTREE */ + haddr_t tmp_addr; /* temporary variable for address */ + + TESTING("File's free-space managers are persistent for split-file"); + + /* for now, we don't support persistant free space managers + * with the split file driver. + */ + SKIPPED(); + HDfprintf(stdout, " Persistant FSMs disabled in multi file driver.\n"); + return 0; /* <========== note return */ + + /* File creation property list template */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + + /* for now, we don't support persistant free space managers + * with the split file driver. + */ + SKIPPED(); + HDfprintf(stdout, " Persistant FSMs disabled in multi file driver.\n"); + return 0; /* <========== note return */ + + /* File creation property list template */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + + if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) + FAIL_STACK_ERROR + + /* Set up split driver */ + if(H5Pset_fapl_split(fapl, "-m.h5", H5P_DEFAULT, "-r.h5", H5P_DEFAULT)<0) + FAIL_STACK_ERROR + + /* File creation property list template */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_FSM_AGGR, TRUE, (hsize_t)1) < 0) + FAIL_STACK_ERROR + + /* 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, fcpl, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate 4 blocks of type H5FD_MEM_SUPER */ + type = H5FD_MEM_SUPER; + if(HADDR_UNDEF == (addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr4 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE4))) + FAIL_STACK_ERROR + + /* Put block #1, #3 into H5FD_MEM_SUPER free-space manager */ + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE1) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE3) < 0) + FAIL_STACK_ERROR + + /* Allocate 4 blocks of type H5FD_MEM_DRAW */ + stype = H5FD_MEM_DRAW; + if(HADDR_UNDEF == (saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (saddr2 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (saddr3 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (saddr4 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE4))) + FAIL_STACK_ERROR + + /* Put block #1, #3 into H5FD_MEM_DRAW free-space manager */ + if(H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE1) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr3, (hsize_t)TBLOCK_SIZE3) < 0) + FAIL_STACK_ERROR + + 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Verify that the H5FD_MEM_SUPER free-space manager is there */ + if(!H5F_addr_defined(f->shared->fs_addr[type])) + TEST_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)type) < 0) + FAIL_STACK_ERROR + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[type], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* Verify free-space info */ + if(fs_stat.tot_space < (TBLOCK_SIZE1+TBLOCK_SIZE3)) + TEST_ERROR + if(fs_stat.serial_sect_count < 2) + TEST_ERROR + + /* Retrieve block #1 from H5FD_MEM_SUPER free-space manager; block #3 still in free-space */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(tmp_addr != addr1) + TEST_ERROR + + /* Verify that the free-space manager for H5FD_MEM_DRAW is there */ + if(!H5F_addr_defined(f->shared->fs_addr[stype])) + TEST_ERROR + + + /* Start up H5FD_MEM_DRAW free-space manager */ + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)stype) < 0) + FAIL_STACK_ERROR + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[stype], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* Verify free-space info */ + if(fs_stat.tot_space < (TBLOCK_SIZE1+TBLOCK_SIZE3)) + TEST_ERROR + if(fs_stat.serial_sect_count < 2) + TEST_ERROR + + /* Retrieve blocks #1 from H5FD_MEM_DRAW free-space manager */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(tmp_addr != saddr1) + TEST_ERROR + + /* Retrieve blocks #3 from H5FD_MEM_DRAW free-space manager */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(tmp_addr != saddr3) + TEST_ERROR + /* H5FD_MEM_DRAW free-space manager is going away at closing */ + /* works for this one because the freeing of sect_addr is to H5FD_MEM_SUPER fs, not against itself */ + + /* Allocate 4 blocks of type H5FD_MEM_BTREE */ + btype = H5FD_MEM_BTREE; + if(HADDR_UNDEF == (baddr5 = H5MF_alloc(f, btype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (baddr6 = H5MF_alloc(f, btype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE6))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (baddr7 = H5MF_alloc(f, btype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE7))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (baddr8 = H5MF_alloc(f, btype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE8))) + FAIL_STACK_ERROR + + /* Put block #5 & #7 into H5FD_MEM_BTREE free-space manager */ + if(H5MF_xfree(f, btype, H5AC_ind_read_dxpl_id, baddr5, (hsize_t)TBLOCK_SIZE5) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, btype, H5AC_ind_read_dxpl_id, baddr7, (hsize_t)TBLOCK_SIZE7) < 0) + FAIL_STACK_ERROR + + 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Verify that the free-space manager for H5FD_MEM_DRAW is not there */ + if(H5F_addr_defined(f->shared->fs_addr[stype])) + TEST_ERROR + + /* Verify that the free-space manager for H5FD_MEM_SUPER is there */ + if(!H5F_addr_defined(f->shared->fs_addr[type])) + TEST_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)type) < 0) + FAIL_STACK_ERROR + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[type], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* Verify free-space info */ + if(fs_stat.tot_space < (TBLOCK_SIZE3+TBLOCK_SIZE5+TBLOCK_SIZE7)) + TEST_ERROR + + /* Retrieve block #3 from H5FD_MEM_SUPER free-space manager */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(tmp_addr != addr3) + TEST_ERROR + + /* Retrieve block #7 from H5FD_MEM_BTREE free-space manager */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, btype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE7))) + FAIL_STACK_ERROR + if(tmp_addr != baddr7) + TEST_ERROR + + /* There should still be block #5 of H5FD_MEM_BTREE in H5FD_MEM_BTREE free-space manager */ + 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Verify that the H5FD_MEM_SUPER free-space manager is there */ + if(!H5F_addr_defined(f->shared->fs_addr[type])) + TEST_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)type) < 0) + FAIL_STACK_ERROR + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[type], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* Verify free-space info */ + if(fs_stat.tot_space < TBLOCK_SIZE5) + TEST_ERROR + + /* Closing */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + if(H5Pclose(fapl) < 0) + FAIL_STACK_ERROR + if(H5Pclose(fcpl) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + H5Pclose(fcpl); + H5Pclose(fapl); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_persist_split() */ + +#define MULTI_SETUP(memb_map, memb_fapl, memb_name, memb_addr, sv) { \ + H5FD_mem_t mt; \ + HDmemset(memb_map, 0, sizeof memb_map); \ + HDmemset(memb_fapl, 0, sizeof memb_fapl); \ + HDmemset(memb_name, 0, sizeof memb_name); \ + HDmemset(memb_addr, 0, sizeof memb_addr); \ + HDmemset(sv, 0, sizeof sv); \ + for(mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, mt)) { \ + memb_map[mt] = H5FD_MEM_SUPER; \ + memb_fapl[mt] = H5P_DEFAULT; \ + } \ + memb_map[H5FD_MEM_BTREE] = H5FD_MEM_BTREE; \ + memb_map[H5FD_MEM_DRAW] = H5FD_MEM_DRAW; \ + memb_map[H5FD_MEM_GHEAP] = H5FD_MEM_GHEAP; \ + memb_map[H5FD_MEM_LHEAP] = H5FD_MEM_LHEAP; \ + sprintf(sv[H5FD_MEM_SUPER], "%%s-%c.h5", 's'); \ + memb_name[H5FD_MEM_SUPER] = sv[H5FD_MEM_SUPER]; \ + memb_addr[H5FD_MEM_SUPER] = 0; \ + sprintf(sv[H5FD_MEM_BTREE], "%%s-%c.h5", 'b'); \ + memb_name[H5FD_MEM_BTREE] = sv[H5FD_MEM_BTREE]; \ + memb_addr[H5FD_MEM_BTREE] = HADDR_MAX/6; \ + sprintf(sv[H5FD_MEM_DRAW], "%%s-%c.h5", 'r'); \ + memb_name[H5FD_MEM_DRAW] = sv[H5FD_MEM_DRAW]; \ + memb_addr[H5FD_MEM_DRAW] = HADDR_MAX/3; \ + sprintf(sv[H5FD_MEM_GHEAP], "%%s-%c.h5", 'g'); \ + memb_name[H5FD_MEM_GHEAP] = sv[H5FD_MEM_GHEAP]; \ + memb_addr[H5FD_MEM_GHEAP] = HADDR_MAX/2; \ + sprintf(sv[H5FD_MEM_LHEAP], "%%s-%c.h5", 'l'); \ + memb_name[H5FD_MEM_LHEAP] = sv[H5FD_MEM_LHEAP]; \ + memb_addr[H5FD_MEM_LHEAP] = HADDR_MAX*2/3; \ + sprintf(sv[H5FD_MEM_OHDR], "%%s-%c.h5", 'o'); \ + memb_name[H5FD_MEM_OHDR] = sv[H5FD_MEM_OHDR]; \ + memb_addr[H5FD_MEM_OHDR] = HADDR_MAX*5/6; \ +} + +/* + *------------------------------------------------------------------------- + * Verify that the file's free-space manager(s) are persistent for a multi-file + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_fs_persist_multi(void) +{ + hid_t file = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list ID */ + hid_t fapl = -1; /* File access property list ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FD_mem_t type, stype, btype, gtype; /* File allocation type */ + H5FS_stat_t fs_stat; /* Information for free-space manager */ + haddr_t addr1, addr2, addr3, addr4; /* File allocation type */ + haddr_t saddr1, saddr2, saddr3, saddr4; /* File address for H5FD_MEM_SUPER */ + haddr_t baddr1, baddr2, baddr3, baddr4; /* File address for H5FD_MEM_DRAW */ + haddr_t gaddr1, gaddr2; /* File address for H5FD_MEM_GHEAP */ + haddr_t tmp_addr; /* Temporary variable for address */ + H5FS_section_info_t *node; /* Free space section node */ + htri_t node_found = FALSE; /* Indicate section is in free-space */ + H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; /* Memory usage map */ + hid_t memb_fapl[H5FD_MEM_NTYPES]; /* Member access properties */ + char sv[H5FD_MEM_NTYPES][64]; /* Name generators */ + const char *memb_name[H5FD_MEM_NTYPES]; /* Name generators */ + haddr_t memb_addr[H5FD_MEM_NTYPES]; /* Member starting address */ + + + TESTING("File's free-space managers are persistent for multi-file"); + + /* for now, we don't support persistant free space managers + * with the multi file driver. + */ + SKIPPED(); + HDfprintf(stdout, " Persistant FSMs disabled in multi file driver.\n"); + return 0; /* <========== note return */ + + /* for now, we don't support persistant free space managers + * with the multi file driver. + */ + SKIPPED(); + HDfprintf(stdout, " Persistant FSMs disabled in multi file driver.\n"); + return 0; /* <========== note return */ + + /* File creation property list template */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_FSM_AGGR, TRUE, (hsize_t)1) < 0) + FAIL_STACK_ERROR + + if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) + FAIL_STACK_ERROR + + MULTI_SETUP(memb_map, memb_fapl, memb_name, memb_addr, sv) + + if(H5Pset_fapl_multi(fapl, memb_map, memb_fapl, memb_name, memb_addr, TRUE) < 0) + TEST_ERROR; + + /* 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, fcpl, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate 4 blocks of type H5FD_MEM_SUPER */ + type = H5FD_MEM_SUPER; + if(HADDR_UNDEF == (addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr4 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE4))) + FAIL_STACK_ERROR + + /* Put block #1, #3 into H5FD_MEM_SUPER free-space manager */ + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE1) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE3) < 0) + FAIL_STACK_ERROR + + /* Allocate 4 blocks of type H5FD_MEM_DRAW */ + stype = H5FD_MEM_DRAW; + if(HADDR_UNDEF == (saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (saddr2 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (saddr3 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (saddr4 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE4))) + FAIL_STACK_ERROR + + /* Put block #1, #3 into H5FD_MEM_DRAW free-space manager */ + if(H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE1) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr3, (hsize_t)TBLOCK_SIZE3) < 0) + FAIL_STACK_ERROR + + 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Verify that the H5FD_MEM_SUPER free-space manager is there */ + if(!H5F_addr_defined(f->shared->fs_addr[type])) + TEST_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)type) < 0) + FAIL_STACK_ERROR + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[type], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* Verify free-space info */ + if(fs_stat.tot_space < (TBLOCK_SIZE1+TBLOCK_SIZE3)) + TEST_ERROR + if(fs_stat.serial_sect_count < 2) + TEST_ERROR + + /* Retrieve block #1 from H5FD_MEM_SUPER free-space manager; block #3 still in free-space */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(tmp_addr != addr1) + TEST_ERROR + + /* Verify that the free-space manager for H5FD_MEM_DRAW is there */ + if(!H5F_addr_defined(f->shared->fs_addr[stype])) + TEST_ERROR + + /* Start up H5FD_MEM_DRAW free-space manager */ + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)stype) < 0) + FAIL_STACK_ERROR + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[stype], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* Verify free-space info */ + if(fs_stat.tot_space < (TBLOCK_SIZE1+TBLOCK_SIZE3)) + TEST_ERROR + if(fs_stat.serial_sect_count < 2) + TEST_ERROR + + /* Retrieve blocks #1 from H5FD_MEM_DRAW free-space manager */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(tmp_addr != saddr1) + TEST_ERROR + + /* Retrieve blocks #3 from H5FD_MEM_DRAW free-space manager */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(tmp_addr != saddr3) + TEST_ERROR + + /* Allocate 4 blocks of type H5FD_MEM_BTREE */ + btype = H5FD_MEM_BTREE; + if(HADDR_UNDEF == (baddr1 = H5MF_alloc(f, btype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (baddr2 = H5MF_alloc(f, btype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (baddr3 = H5MF_alloc(f, btype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (baddr4 = H5MF_alloc(f, btype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE4))) + FAIL_STACK_ERROR + + /* Put block #1 & #3 into H5FD_MEM_BTREE free-space manager */ + if(H5MF_xfree(f, btype, H5AC_ind_read_dxpl_id, baddr1, (hsize_t)TBLOCK_SIZE1) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, btype, H5AC_ind_read_dxpl_id, baddr3, (hsize_t)TBLOCK_SIZE3) < 0) + FAIL_STACK_ERROR + + 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Verify that the free-space manager for H5FD_MEM_SUPER is there */ + if(!H5F_addr_defined(f->shared->fs_addr[type])) + TEST_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)type) < 0) + FAIL_STACK_ERROR + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[type], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* Verify free-space info */ + if(fs_stat.tot_space < TBLOCK_SIZE3) + TEST_ERROR + + /* Retrieve block #3 from H5FD_MEM_SUPER free-space manager */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(tmp_addr != addr3) + TEST_ERROR + + /* Verify that the free-space manager for H5FD_MEM_DRAW is not there */ + if(H5F_addr_defined(f->shared->fs_addr[stype])) + TEST_ERROR + + /* Verify that the free-space manager for H5FD_MEM_BTREE is there */ + if(!H5F_addr_defined(f->shared->fs_addr[btype])) + TEST_ERROR + + /* Start up H5FD_MEM_BTREE free-space manager */ + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)btype) < 0) + FAIL_STACK_ERROR + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[btype], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* Verify free-space info */ + if(fs_stat.tot_space < (TBLOCK_SIZE1+TBLOCK_SIZE3)) + TEST_ERROR + if(fs_stat.serial_sect_count < 2) + TEST_ERROR + + /* Allocate 2 blocks of type H5FD_MEM_GHEAP */ + gtype = H5FD_MEM_GHEAP; + if(HADDR_UNDEF == (gaddr2 = H5MF_alloc(f, gtype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (gaddr1 = H5MF_alloc(f, gtype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + + /* Put block #2 into H5FD_MEM_GHEAP free-space manager */ + if(H5MF_xfree(f, gtype, H5AC_ind_read_dxpl_id, gaddr2, (hsize_t)TBLOCK_SIZE2) < 0) + FAIL_STACK_ERROR + + 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* If H5FD_MEM_SUPER is there, should not find block #1 & #3 */ + if(H5F_addr_defined(f->shared->fs_addr[type])) { + /* Start up H5FD_MEM_SUPER free-space manager */ + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)type) < 0) + FAIL_STACK_ERROR + + if((node_found = H5FS_sect_find(f, H5AC_ind_read_dxpl_id, f->shared->fs_man[type], + (hsize_t)TBLOCK_SIZE1, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + if(node_found) TEST_ERROR + + if((node_found = H5FS_sect_find(f, H5AC_ind_read_dxpl_id, f->shared->fs_man[type], + (hsize_t)TBLOCK_SIZE3, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + if(node_found) TEST_ERROR + } + + /* Verify that the H5FD_MEM_GHEAP free-space manager is there */ + if(!H5F_addr_defined(f->shared->fs_addr[gtype])) + TEST_ERROR + + /* Start up H5FD_MEM_GHEAP free-space manager */ + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)gtype) < 0) + FAIL_STACK_ERROR + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[gtype], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* Verify free-space info */ + if(fs_stat.tot_space < TBLOCK_SIZE2) + TEST_ERROR + + /* Closing */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + if(H5Pclose(fapl) < 0) + FAIL_STACK_ERROR + if(H5Pclose(fcpl) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + H5Pclose(fcpl); + H5Pclose(fapl); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_persist_multi() */ + +/* + *------------------------------------------------------------------------- + * Verify that the file's free-space persists where there are free sections in the manager + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_fs_persist(const char *env_h5_drvr, hid_t fapl, hbool_t new_format) +{ + hid_t file = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list ID */ + hid_t fapl2 = -1; /* File access property list ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FD_mem_t type; /* File allocation type */ + H5FD_mem_t tt; /* File allocation type */ + H5FS_stat_t fs_stat; /* Information for free-space manager */ + haddr_t addr1, addr2, addr3, addr4, addr5, addr6; /* File address for H5FD_MEM_SUPER */ + haddr_t tmp_addr; /* Temporary variable for address */ + + if(new_format) + TESTING("File's free-space is persistent with new library format") + else + TESTING("File's free-space is persistent with old library format") + + if(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")) { + + /* File creation property list template */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + /* Copy the file access property list */ + if((fapl2 = H5Pcopy(fapl)) < 0) FAIL_STACK_ERROR + + if(new_format) { + /* Latest format */ + if(H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) + FAIL_STACK_ERROR + /* Set to paged aggregation and persisting free-space */ + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, TRUE, (hsize_t)1) < 0) + TEST_ERROR + } else { + /* Setting: aggregation with persisting free-space */ + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_FSM_AGGR, TRUE, (hsize_t)1) < 0) + TEST_ERROR + } + + /* 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, fcpl, fapl2)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate 6 blocks */ + type = H5FD_MEM_SUPER; + if(HADDR_UNDEF == (addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr4 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE4))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr5 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr6 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE6))) + FAIL_STACK_ERROR + + /* Put block #1, #3, #5 to H5FD_MEM_SUPER free-space manager */ + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE1) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE3) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr5, (hsize_t)TBLOCK_SIZE5) < 0) + FAIL_STACK_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl2)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_alloc_to_fs_type(f, type, TBLOCK_SIZE6, (H5F_mem_page_t *)&tt); + + /* Verify that H5FD_MEM_SUPER free-space manager is there */ + if(!H5F_addr_defined(f->shared->fs_addr[tt])) + TEST_ERROR + + /* Since we are about to open a self referential free space + * manager prior to the first file space allocation / deallocation + * call H5MF_tidy_self_referential_fsm_hack() first so as to avoid + * assertion failures on the first file space alloc / dealloc. + */ + if((f->shared->first_alloc_dealloc) && + (SUCCEED != + H5MF_tidy_self_referential_fsm_hack(f, H5AC_ind_read_dxpl_id))) + FAIL_STACK_ERROR + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(!(f->shared->fs_man[tt])) + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)tt) < 0) + FAIL_STACK_ERROR + + /* Get info for free-space manager */ + if(H5FS_stat_info(f, f->shared->fs_man[tt], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* Verify free-space info */ + if(fs_stat.tot_space < (TBLOCK_SIZE1+TBLOCK_SIZE3+TBLOCK_SIZE5)) + TEST_ERROR + + if(fs_stat.serial_sect_count < 3) + TEST_ERROR + + /* Retrieve block #3 from H5FD_MEM_SUPER free-space manager */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(tmp_addr != addr3) + TEST_ERROR + + /* Retrieve block #1 from H5FD_MEM_SUPER free-space manager */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(tmp_addr != addr1) + TEST_ERROR + + 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Verify that H5FD_MEM_SUPER free-space manager is there */ + if(!H5F_addr_defined(f->shared->fs_addr[tt])) + TEST_ERROR + + /* Retrieve block #5 from H5FD_MEM_SUPER free-space manager */ + if(HADDR_UNDEF == (tmp_addr = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5))) + FAIL_STACK_ERROR + if(tmp_addr != addr5) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + if(H5Pclose(fcpl) < 0) + FAIL_STACK_ERROR + if(H5Pclose(fapl2) < 0) + FAIL_STACK_ERROR + + PASSED() + + } else { + SKIPPED(); + puts(" Current VFD doesn't support persisting free-space or paged aggregation strategy"); + } + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + H5Pclose(fcpl); + H5Pclose(fapl2); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_persist() */ + +/* + *------------------------------------------------------------------------- + * Verify free-space are merged/shrunk away + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_fs_gone(const char *env_h5_drvr, hid_t fapl, hbool_t new_format) +{ + hid_t file = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list */ + hid_t fapl2 = -1; /* File access property list */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FD_mem_t type; /* File allocation type */ + H5FS_stat_t fs_stat; /* Information for free-space manager */ + haddr_t addr1, addr2, addr3, addr4; /* File address for H5FD_MEM_SUPER */ + H5FD_mem_t fs_type; + hbool_t contig_addr_vfd; + hbool_t ran_H5MF_tidy_self_referential_fsm_hack = FALSE; + + if(new_format) + TESTING("File's free-space is going away with new library format") + else + TESTING("File's free-space is going away with old library format") + + /* Current VFD that does not support contigous address space */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + + if(contig_addr_vfd) { + + /* File creation property list template */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + /* Copy the file access property list */ + if((fapl2 = H5Pcopy(fapl)) < 0) FAIL_STACK_ERROR + + if(new_format) + if(H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) + FAIL_STACK_ERROR + + /* Set to aggregation and persisting free-space */ + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_FSM_AGGR, TRUE, (hsize_t)1) < 0) + FAIL_STACK_ERROR + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl2, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl2)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate 4 blocks */ + type = H5FD_MEM_SUPER; + if(HADDR_UNDEF == (addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr4 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE4))) + FAIL_STACK_ERROR + + /* Put block #1, #3 to H5FD_MEM_SUPER free-space manager */ + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE1) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE3) < 0) + FAIL_STACK_ERROR + + /* Retrieve block #1, #3 from H5FD_MEM_SUPER free-space manager */ + if(HADDR_UNDEF == (addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl2)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_alloc_to_fs_type(f, type, TBLOCK_SIZE4, (H5F_mem_page_t *)&fs_type); + + /* Verify that the H5FD_MEM_SUPER free-space manager is not there */ + if(H5F_addr_defined(f->shared->fs_addr[fs_type])) + TEST_ERROR + + /* Put block #3 to H5FD_MEM_SUPER free-space manager */ + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE3) < 0) + FAIL_STACK_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl2)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Verify that H5FD_MEM_SUPER free-space manager is there */ + if(!H5F_addr_defined(f->shared->fs_addr[fs_type])) + TEST_ERROR + + /* Since we are about to open a self referential free space + * manager prior to the first file space allocation / deallocation + * call H5MF_tidy_self_referential_fsm_hack() first so as to avoid + * assertion failures on the first file space alloc / dealloc. + */ + if(f->shared->first_alloc_dealloc){ + if(SUCCEED!=H5MF_tidy_self_referential_fsm_hack(f,H5AC_ind_read_dxpl_id)) + FAIL_STACK_ERROR + ran_H5MF_tidy_self_referential_fsm_hack = TRUE; + } + + /* Start up H5FD_MEM_SUPER free-space manager */ + if(!(f->shared->fs_man[fs_type])) + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, (H5F_mem_page_t)fs_type) < 0) + FAIL_STACK_ERROR + + /* Get info for H5FD_MEM_SUPER free-space manager */ + if(H5FS_stat_info(f, f->shared->fs_man[fs_type], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* if we ran H5MF_tidy_self_referential_fsm_hack(), the + * H5FD_MEM_SUPER free space manager must be floating. + * Thus fs_stat.addr must be undefined. + */ + if((!ran_H5MF_tidy_self_referential_fsm_hack) && + (!H5F_addr_defined(fs_stat.addr))) + TEST_ERROR + + if(fs_stat.tot_space < TBLOCK_SIZE3) + TEST_ERROR + + /* Put block #4 to H5FD_MEM_SUPER free-space manager */ + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr4, (hsize_t)TBLOCK_SIZE4) < 0) + FAIL_STACK_ERROR + + /* The H5FD_MEM_SUPER free-space manager will go away at H5MF_close() */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl2)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Verify that the H5FD_MEM_SUPER free-space manager is not there */ + if(H5F_addr_defined(f->shared->fs_addr[fs_type])) + TEST_ERROR + + /* Closing */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + if(H5Pclose(fcpl) < 0) + FAIL_STACK_ERROR + if(H5Pclose(fapl2) < 0) + FAIL_STACK_ERROR + + PASSED() + + } else { + SKIPPED(); + puts(" Current VFD doesn't support persistent free-space manager"); + } + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + H5Pclose(fcpl); + H5Pclose(fapl2); + } H5E_END_TRY; + return(1); +} /* test_mf_fs_gone() */ + +/* + *------------------------------------------------------------------------- + * Verify that free-space persist with combinations of + * file space strategy and free space threshold as specified. + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_strat_thres_persist(const char *env_h5_drvr, hid_t fapl, hbool_t new_format) +{ + hid_t file = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list template */ + hid_t fapl2 = -1; /* File access property list template */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FD_mem_t type; /* File allocation type */ + H5FD_mem_t tt; /* File allocation type */ + haddr_t addr1, addr2, addr3, addr4, addr5, addr6; /* File address for H5FD_MEM_SUPER */ + H5F_fspace_strategy_t fs_type; /* File space handling strategy */ + hsize_t fs_threshold; /* Free-space section threshold */ + unsigned fs_persist; /* To persist free-space or not */ + hbool_t contig_addr_vfd; + + if(new_format) + TESTING("File space strategy/persisting/threshold with new library format") + else + TESTING("File space strategy/persisting/threshold with old library format") + + /* Current VFD that does not support contigous address space */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Copy the file access property list */ + if((fapl2 = H5Pcopy(fapl)) < 0) + FAIL_STACK_ERROR + + if(new_format) + if(H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) + FAIL_STACK_ERROR + + /* Test with TRUE or FALSE for persisting free-space */ + for(fs_persist = FALSE; fs_persist <= TRUE; fs_persist++) { + + for(fs_threshold = 0; fs_threshold <= TEST_THRESHOLD10; fs_threshold++) { + + /* Testing for H5F_FSPACE_STRATEGY_FSM_AGGR and H5F_FSPACE_STRATEGY_PAGE strategies only */ + for(fs_type = H5F_FSPACE_STRATEGY_FSM_AGGR; fs_type < H5F_FSPACE_STRATEGY_AGGR; H5_INC_ENUM(H5F_fspace_strategy_t, fs_type)) { + + if(!contig_addr_vfd && (fs_persist || fs_type == H5F_FSPACE_STRATEGY_PAGE)) + continue; + + /* Create file-creation template */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + /* Set default file space information */ + if(H5Pset_file_space_strategy(fcpl, fs_type, (hbool_t)fs_persist, fs_threshold) < 0) + FAIL_STACK_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl2)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate 6 blocks */ + type = H5FD_MEM_SUPER; + if(HADDR_UNDEF == (addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr4 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE4))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr5 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr6 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE6))) + FAIL_STACK_ERROR + + /* Put block #1, #3, #5 to H5FD_MEM_SUPER free-space manager */ + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE1) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE3) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr5, (hsize_t)TBLOCK_SIZE5) < 0) + FAIL_STACK_ERROR + + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl2)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + H5MF_alloc_to_fs_type(f, type, TBLOCK_SIZE6, (H5F_mem_page_t *)&tt); + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + if(f->shared->fs_persist) { + hssize_t nsects; /* # of free-space sections */ + int i; /* local index variable */ + H5F_sect_info_t *sect_info; /* array to hold the free-space information */ + + /* Get the # of free-space sections in the file */ + if((nsects = H5Fget_free_sections(file, H5FD_MEM_DEFAULT, (size_t)0, NULL)) < 0) + FAIL_STACK_ERROR + + /* Verify no free-space sections */ + /* paged aggregation has 1 section for last_small */ + if(fs_threshold > TBLOCK_SIZE5 && nsects && fs_type != H5F_FSPACE_STRATEGY_PAGE) + TEST_ERROR + + if(nsects) { + /* Allocate storage for the free space section information */ + sect_info = (H5F_sect_info_t *)HDcalloc((size_t)nsects, sizeof(H5F_sect_info_t)); + + H5Fget_free_sections(file, H5FD_MEM_DEFAULT, (size_t)nsects, sect_info); + + /* Verify the size of free-space sections */ + for(i = 0; i < nsects; i++) + if(sect_info[i].size < fs_threshold) + TEST_ERROR + if(sect_info) + HDfree(sect_info); + } + } else { + if(H5F_addr_defined(f->shared->fs_addr[tt])) + TEST_ERROR + } + + /* Closing */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + if(H5Pclose(fcpl) < 0) + FAIL_STACK_ERROR + } /* end for fs_type */ + } /* end for fs_threshold */ + } /* end for fs_persist */ + + if(H5Pclose(fapl2) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Pclose(fcpl); + H5Pclose(fapl2); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_strat_thres_persist() */ + +/* + *------------------------------------------------------------------------- + * Verify free-space are merged/shrunk away with file space settings: + * --strategy, persist/not persist file space + *------------------------------------------------------------------------- + */ +static unsigned +test_mf_strat_thres_gone(const char *env_h5_drvr, hid_t fapl, hbool_t new_format) +{ + hid_t file = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list template */ + hid_t fapl2 = -1; /* File access property list template */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FD_mem_t type; /* File allocation type */ + H5FD_mem_t tt; /* File allocation type */ + haddr_t addr1, addr2, addr3, addr4, addr5, addr6; /* File address for H5FD_MEM_SUPER */ + H5F_fspace_strategy_t fs_type; /* File space handling strategy */ + unsigned fs_persist; /* To persist free-space or not */ + H5FS_stat_t fs_state; /* Information for free-space manager */ + H5FS_stat_t fs_state_zero; /* Information for free-space manager */ + hbool_t contig_addr_vfd; + + if(new_format) + TESTING("File space merge/shrink for section size < threshold with new library format") + else + TESTING("File space merge/shrink for section size < threshold with old library format") + + /* Current VFD that does not support contigous address space */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + HDmemset(&fs_state_zero, 0, sizeof(H5FS_stat_t)); + + /* Copy the file access property list */ + if((fapl2 = H5Pcopy(fapl)) < 0) + FAIL_STACK_ERROR + + if(new_format) + if(H5Pset_libver_bounds(fapl2, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) + FAIL_STACK_ERROR + + /* Test with TRUE or FALSE for persisting free-space */ + for(fs_persist = FALSE; fs_persist <= TRUE; fs_persist++) { + /* Testing for H5F_FSPACE_STRATEGY_FSM_AGGR and H5F_FSPACE_STRATEGY_PAGE strategies only */ + for(fs_type = H5F_FSPACE_STRATEGY_FSM_AGGR; fs_type < H5F_FSPACE_STRATEGY_AGGR; H5_INC_ENUM(H5F_fspace_strategy_t, fs_type)) { + + /* Skip for multi/split driver: persisting free-space or paged aggregation strategy */ + if(!contig_addr_vfd && (fs_persist || fs_type == H5F_FSPACE_STRATEGY_PAGE)) + continue; + + /* Clear out free-space statistics */ + HDmemset(&fs_state, 0, sizeof(H5FS_stat_t)); + + /* Create file-creation template */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + /* Set default file space information */ + if(H5Pset_file_space_strategy(fcpl, fs_type, fs_persist, (hsize_t)TEST_THRESHOLD3) < 0) + FAIL_STACK_ERROR + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl2)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate 6 blocks */ + type = H5FD_MEM_SUPER; + if(HADDR_UNDEF == (addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr2 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE2))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr4 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE4))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr5 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5))) + FAIL_STACK_ERROR + if(HADDR_UNDEF == (addr6 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE6))) + FAIL_STACK_ERROR + + H5MF_alloc_to_fs_type(f, type, TBLOCK_SIZE6, (H5F_mem_page_t *)&tt); + + /* For paged aggregation, the section in the page at EOF for small meta fs is not shrunk away */ + if(fs_type == H5F_FSPACE_STRATEGY_PAGE) { + if(H5FS_stat_info(f, f->shared->fs_man[tt], &fs_state) < 0) + FAIL_STACK_ERROR + } + + /* Put block #3, #5 to H5FD_MEM_SUPER free-space manager */ + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE3) < 0) + FAIL_STACK_ERROR + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr5, (hsize_t)TBLOCK_SIZE5) < 0) + FAIL_STACK_ERROR + + fs_state.tot_space += TBLOCK_SIZE3 + TBLOCK_SIZE5; + fs_state.tot_sect_count += 2; + fs_state.serial_sect_count += 2; + + if(check_stats(f, f->shared->fs_man[tt], &fs_state)) + TEST_ERROR + + /* section #2 is less than threshold but is merged into section #3 */ + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE2) < 0) + FAIL_STACK_ERROR + + fs_state.tot_space += TBLOCK_SIZE2; + if(check_stats(f, f->shared->fs_man[tt], &fs_state)) + TEST_ERROR + + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr4, (hsize_t)TBLOCK_SIZE4) < 0) + FAIL_STACK_ERROR + + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr6, (hsize_t)TBLOCK_SIZE6) < 0) + FAIL_STACK_ERROR + + /* For paged aggregation, the sections in the page at EOF for small meta fs are merged but are not shrunk away */ + if(fs_type == H5F_FSPACE_STRATEGY_PAGE) { + fs_state.tot_sect_count = fs_state.serial_sect_count = 1; + fs_state.tot_space += (TBLOCK_SIZE4 + TBLOCK_SIZE6); + } + + /* For old format: the sections at EOF are shrunk away */ + if(check_stats(f, f->shared->fs_man[tt], (fs_type == H5F_FSPACE_STRATEGY_PAGE) ? &fs_state:&fs_state_zero)) + TEST_ERROR + + /* section #1 is less than threshold but is shrunk away */ + if(H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE1) < 0) + FAIL_STACK_ERROR + + /* For paged aggregation, the section in the page at EOF for small meta fs is not shrunk away */ + if(fs_type == H5F_FSPACE_STRATEGY_PAGE) + fs_state.tot_space += TBLOCK_SIZE1; + + /* For old format: the sections at EOF are shrunk away */ + if(check_stats(f, f->shared->fs_man[tt], (fs_type == H5F_FSPACE_STRATEGY_PAGE) ? &fs_state : &fs_state_zero)) + TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl2)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Free-space manager should be empty */ + if(!(fs_type == H5F_FSPACE_STRATEGY_PAGE && fs_persist)) + if(H5F_addr_defined(f->shared->fs_addr[tt])) + TEST_ERROR + + /* Closing */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + if(H5Pclose(fcpl) < 0) + FAIL_STACK_ERROR + } /* end for fs_type */ + } /* end for fs_persist */ + + if(H5Pclose(fapl2) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Pclose(fcpl); + H5Pclose(fapl2); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_mf_strat_thres_gone() */ + +/* + *------------------------------------------------------------------------- + * To verify that file space is allocated from the corresponding free-space manager + * because H5FD_FLMAP_DICHOTOMY is used as the default free-list mapping. + * + * (1) Allocate the first block (size 30) of type H5FD_MEM_SUPER + * (2) Allocate the second block (size 50) of type H5FD_MEM_SUPER + * + * (3) Allocate the first block (size 30) of type H5FD_MEM_DRAW + * + * (4) Free the first block (size 30) of type H5FD_MEM_SUPER + * + * (5) Allocate the second block (size 30) of type H5FD_MEM_DRAW + * (6) Verify that this second block is not the freed block from (3) + * + * (7) Allocate the second block (size 30) of type H5FD_MEM_DRAW + * (8) Free the first block (size 30) of type H5FD_MEM_DRAW + * + * (9) Allocate the third block (size 30) of type H5FD_MEM_SUPER + * (10) Verify that this third block is not freed block from (8) + *------------------------------------------------------------------------- + */ +static unsigned +test_dichotomy(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FD_mem_t type, stype; + haddr_t addr1, addr3, saddr1, saddr2; + + TESTING("Allocation from raw or metadata free-space manager"); + + /* 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 = (H5F_t *)H5I_object(file))) + FAIL_STACK_ERROR + + /* Allocate the first block of type H5FD_MEM_SUPER */ + type = H5FD_MEM_SUPER; + addr1 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Allocate the second block of type H5FD_MEM_SUPER */ + H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Allocate the first block of type H5FD_MEM_DRAW */ + stype = H5FD_MEM_DRAW; + saddr1 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Free the first block of type H5FD_MEM_SUPER */ + H5MF_xfree(f, type, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE30); + + /* Allocate the second block of type H5FD_MEM_DRAW */ + saddr2 = H5MF_alloc(f, stype, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that saddr1 is not addr1 */ + if(saddr2 == addr1) TEST_ERROR + + /* Free the first block of type H5FD_MEM_DRAW */ + H5MF_xfree(f, stype, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE30); + + /* Allocate the third block of type H5FD_MEM_SUPER */ + addr3 = H5MF_alloc(f, type, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + + /* Verify that addr3 is not saddr1 */ + if(addr3 == saddr1) TEST_ERROR + + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_dichotomy() */ + +/* + *------------------------------------------------------------------------- + * set_multi_split(): + * Internal routine to set up page-aligned address space for multi/split driver + * when testing paged aggregation. + *------------------------------------------------------------------------- + */ +static int +set_multi_split(hid_t fapl, hsize_t pagesize, hbool_t multi, hbool_t split) +{ + H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; + hid_t memb_fapl_arr[H5FD_MEM_NTYPES]; + char *memb_name[H5FD_MEM_NTYPES]; + haddr_t memb_addr[H5FD_MEM_NTYPES]; + hbool_t relax; + H5FD_mem_t mt; + + HDassert(multi || split); + + HDmemset(memb_name, 0, sizeof memb_name); + + /* Get current split settings */ + if(H5Pget_fapl_multi(fapl, memb_map, memb_fapl_arr, memb_name, memb_addr, &relax) < 0) + TEST_ERROR + + if(split) { + /* Set memb_addr aligned */ + memb_addr[H5FD_MEM_SUPER] = ((memb_addr[H5FD_MEM_SUPER] + pagesize - 1) / pagesize) * pagesize; + memb_addr[H5FD_MEM_DRAW] = ((memb_addr[H5FD_MEM_DRAW] + pagesize - 1) / pagesize) * pagesize; + } else { + /* Set memb_addr aligned */ + for(mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, mt)) + memb_addr[mt] = ((memb_addr[mt] + pagesize - 1) / pagesize) * pagesize; + } /* end else */ + + /* Set multi driver with new FAPLs */ + if(H5Pset_fapl_multi(fapl, memb_map, memb_fapl_arr, (const char * const *)memb_name, memb_addr, relax) < 0) + TEST_ERROR + + /* Free memb_name */ + for(mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, mt)) + free(memb_name[mt]); + + return 0; + +error: + return(-1); +} /* set_multi_split() */ + +/*------------------------------------------------------------------------- + * Function: test_page_alloc_xfree + * + * Purpose: To verify allocations and de-allocations for large/small + * sections are done properly when paged aggregation is enabled. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi; Jan 2013 + * + *------------------------------------------------------------------------- + */ +static unsigned +test_page_alloc_xfree(const char *env_h5_drvr, hid_t fapl) +{ + + hid_t fid = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list */ + hid_t fapl_new = -1; /* File access property list ID */ + H5F_t *f = NULL; /* Internal file object pointer */ + haddr_t addr2, addr3; /* Addresses for small meta data blocks */ + haddr_t saddr1; /* Addresses for small raw data blocks */ + haddr_t gaddr1; /* Addresses for large data blocks */ + hbool_t split = FALSE, multi = FALSE; + char filename[FILENAME_LEN]; /* Filename to use */ + haddr_t found_addr; /* Address of the found section */ + unsigned fs_persist; /* To persist free-space or not */ + + TESTING("Paged aggregation for file space: H5MF_alloc/H5MF_xfree"); + + /* Check for split or multi driver */ + if(!HDstrcmp(env_h5_drvr, "split")) + split = TRUE; + else if(!HDstrcmp(env_h5_drvr, "multi")) + multi = TRUE; + + if(!multi && !split) { + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + if(multi || split) + if(set_multi_split(fapl_new, 4096, multi, split) < 0) + TEST_ERROR; + + /* Test with TRUE or FALSE for persisting free-space */ + for(fs_persist = FALSE; fs_persist <= TRUE; fs_persist++) { + H5F_mem_page_t fs_type; + + /* File creation property list */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + TEST_ERROR + + /* Set the strategy to paged aggregation */ + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, fs_persist, (hsize_t)1) < 0) + TEST_ERROR + + /* Create the file to work on */ + if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl_new)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) + TEST_ERROR + + /* Allocate 3 small meta data blocks: addr1, addr2, addr3 */ + H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + addr2 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1034); + addr3 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Free the block with addr2 */ + H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE1034); + + if(!fs_persist) { + + H5MF_alloc_to_fs_type(f, H5FD_MEM_OHDR, TBLOCK_SIZE1034, (H5F_mem_page_t *)&fs_type); + + /* Verify that the freed block with addr2 is found from the small meta data manager */ + if(H5MF_find_sect(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1034, f->shared->fs_man[fs_type], &found_addr) < 0) + TEST_ERROR + if(found_addr != addr2) + TEST_ERROR + } /* end if */ + + /* Allocate 2 small raw data blocks: saddr1, saddr2 */ + saddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE1034); + + /* Free the block with saddr1 */ + H5MF_xfree(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE30); + + if(!fs_persist) { + /* Verify that the freed block with saddr1 is found from the small raw data manager */ + if(H5MF_find_sect(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30, f->shared->fs_man[H5F_MEM_PAGE_DRAW], &found_addr) < 0) + TEST_ERROR + if(found_addr != saddr1) + TEST_ERROR + } /* end if */ + + /* Allocate 2 large data blocks: gaddr1, gaddr2 */ + gaddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5000); + H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE8000); + + /* Free the block with gaddr1 */ + H5MF_xfree(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, gaddr1, (hsize_t)TBLOCK_SIZE5000); + + if(!fs_persist) { + + H5MF_alloc_to_fs_type(f, H5FD_MEM_DRAW, TBLOCK_SIZE5000, (H5F_mem_page_t *)&fs_type); + + /* Verify that the freed block with gaddr1 is found from the large data manager */ + if(H5MF_find_sect(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE8192, f->shared->fs_man[fs_type], &found_addr) < 0) + TEST_ERROR + if(found_addr != gaddr1) + TEST_ERROR + } /* end if */ + + /* Close file */ + if(H5Fclose(fid) < 0) + TEST_ERROR + + /* Close the property list */ + if(H5Pclose(fcpl) < 0) + TEST_ERROR + + if(fs_persist) { + /* Re-open the file */ + if((fid = H5Fopen(filename, H5F_ACC_RDWR, fapl_new)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) + TEST_ERROR + + /* Verify that the large generic manager is there */ + H5MF_alloc_to_fs_type(f, H5FD_MEM_DRAW, TBLOCK_SIZE5000, (H5F_mem_page_t *)&fs_type); + if(!H5F_addr_defined(f->shared->fs_addr[fs_type])) + TEST_ERROR + + /* Verify that the small meta data manager is there */ + H5MF_alloc_to_fs_type(f, H5FD_MEM_OHDR, f->shared->fs_page_size - 1, (H5F_mem_page_t *)&fs_type); + if(!H5F_addr_defined(f->shared->fs_addr[fs_type])) + TEST_ERROR + + /* Since we are about to open a self referential free space + * manager prior to the first file space allocation / deallocation + * call H5MF_tidy_self_referential_fsm_hack() first so as to avoid + * assertion failures on the first file space alloc / dealloc. + */ + if(f->shared->first_alloc_dealloc){ + if(SUCCEED!=H5MF_tidy_self_referential_fsm_hack(f,H5AC_ind_read_dxpl_id)) + FAIL_STACK_ERROR + } + + /* Set up to use the small meta data manager */ + if(!(f->shared->fs_man[fs_type])) + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, fs_type) < 0) + TEST_ERROR + + /* Verify that the freed block with addr2 is found from the small meta data manager */ + if(H5MF_find_sect(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)(f->shared->fs_page_size-(addr3+TBLOCK_SIZE50)), f->shared->fs_man[fs_type], &found_addr) < 0) + TEST_ERROR + + if(found_addr != (addr3+TBLOCK_SIZE50)) + TEST_ERROR + + /* Verify that the small raw data manager is there */ + if(!H5F_addr_defined(f->shared->fs_addr[H5F_MEM_PAGE_DRAW])) + TEST_ERROR + + /* Set up to use the small raw data manager */ + if(!(f->shared->fs_man[H5F_MEM_PAGE_DRAW])) + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, H5F_MEM_PAGE_DRAW) < 0) + TEST_ERROR + + /* Verify that the freed block with saddr1 is found from the small raw data manager */ + if(H5MF_find_sect(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30, f->shared->fs_man[H5F_MEM_PAGE_DRAW], &found_addr) < 0) + TEST_ERROR + if(found_addr != saddr1) + TEST_ERROR + + H5MF_alloc_to_fs_type(f, H5FD_MEM_DRAW, TBLOCK_SIZE5000, (H5F_mem_page_t *)&fs_type); + + if(!(f->shared->fs_man[fs_type])) + /* Set up to use the large data manager */ + if(H5MF_open_fstype(f, H5AC_ind_read_dxpl_id, fs_type) < 0) + TEST_ERROR + + /* Verify that the freed block with gaddr1 is found from the large data manager */ + if(H5MF_find_sect(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE8192, f->shared->fs_man[fs_type], &found_addr) < 0) + TEST_ERROR + if(found_addr != gaddr1) + TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) + TEST_ERROR + } /* end if fs_persist */ + } /* end for */ + + if(H5Pclose(fapl_new) < 0) + TEST_ERROR + + PASSED() + + } else { + SKIPPED(); + puts(" Current VFD doesn't support persisting free-space or paged aggregation strategy"); + } + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(fid); + H5Pclose(fcpl); + H5Pclose(fapl_new); + } H5E_END_TRY; + return(1); + +} /* test_page_alloc_xfree() */ + +/*------------------------------------------------------------------------- + * Function: test_page_try_shrink + * + * Purpose: To verify that shrinking via H5MF_try_shrink() work properly + * when paged aggregation is enabled. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi; Jan 2013 + * + *------------------------------------------------------------------------- + */ +static unsigned +test_page_try_shrink(const char *env_h5_drvr, hid_t fapl) +{ + + hid_t fid = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list */ + H5F_t *f = NULL; /* Internal file object pointer */ + haddr_t addr1; /* Address for small meta data block */ + haddr_t saddr1; /* Address for small raw data block */ + haddr_t gaddr1; /* Address for large data block */ + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + htri_t status; /* status from shrinking */ + h5_stat_size_t file_size; /* File size */ + char filename[FILENAME_LEN]; /* Filename to use */ + + TESTING("Paged aggregation for file space: H5MF_try_shrink()"); + + /* Current VFD that does not support continuous address space */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi") ); + + if(contig_addr_vfd) { + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* File creation property list */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + /* Set the strategy to paged aggregation */ + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, (hsize_t)1) < 0) + FAIL_STACK_ERROR + + /* Create the file to work on */ + if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) + FAIL_STACK_ERROR + + /* Allocate a small meta data block with addr1 */ + addr1 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Try to shrink the block with addr1 */ + if((status = H5MF_try_shrink(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE50)) < 0) + FAIL_STACK_ERROR + + /* Couldn't shrink due to the section (remaining space in the page) is in the small meta data free-space manager */ + if(status == TRUE) TEST_ERROR + + /* Allocate a small raw data block with saddr1 */ + saddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Try to shrink the block with saddr1 */ + if((status = H5MF_try_shrink(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE50)) < 0) + FAIL_STACK_ERROR + + /* Couldn't shrink due to the section (remaining space in the page) is in the small raw data free-space manager */ + if(status == TRUE) TEST_ERROR + + /* Allocate a large data block with gaddr1 */ + gaddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5000); + + /* Try to shrink the block with gaddr1 */ + if((status = H5MF_try_shrink(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, gaddr1, (hsize_t)TBLOCK_SIZE5000)) < 0) + FAIL_STACK_ERROR + + /* Couldn't shrink due to the section (remaining space in the page) is in the large-sized free-space manager */ + if(status == TRUE) TEST_ERROR + + /* Free the block with saddr1--merge to become 1 page, then return to the large manager */ + H5MF_xfree(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE50); + + /* Merge all 3 sections and shrunk */ + H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, gaddr1, (hsize_t)TBLOCK_SIZE5000); + + if(H5Fclose(fid) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Should be on page boundary */ + if(file_size % TBLOCK_SIZE4096) + TEST_ERROR + + /* Close the property list */ + if(H5Pclose(fcpl) < 0) + FAIL_STACK_ERROR + + PASSED() + + } else { + SKIPPED(); + puts(" Current VFD doesn't support paged aggregation"); + } + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(fid); + H5Pclose(fcpl); + } H5E_END_TRY; + return(1); + +} /* test_page_try_shrink() */ + +/*------------------------------------------------------------------------- + * Function: test_page_small_try_extend + * + * Purpose: To verify that extending a small block via H5MF_try_extend() works + * properly when paged aggregation is enabled. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi; Jan 2013 + * + *------------------------------------------------------------------------- + */ +static unsigned +test_page_small_try_extend(const char *env_h5_drvr, hid_t fapl) +{ + + hid_t fid = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list */ + H5F_t *f = NULL; /* Internal file object pointer */ + haddr_t addr1, addr2, addr3; /* Addresses for small meta data blocks */ + haddr_t saddr1; /* Address for small raw data block */ + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + htri_t was_extended; /* Whether the block can be extended or not */ + char filename[FILENAME_LEN]; /* Filename to use */ + + TESTING("Paged aggregation for file space: H5MF_try_extend() a small block"); + + /* Current VFD that does not support continuous address space */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi") && HDstrcmp(env_h5_drvr, "family")); + + if(contig_addr_vfd) { + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* File creation property list */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + /* Set the strategy to paged aggregation */ + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, (hsize_t)1) < 0) + FAIL_STACK_ERROR + + /* Create the file to work on */ + if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) + FAIL_STACK_ERROR + + /* Allocate a small meta data block with addr1 */ + addr1 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE98); + + /* Try extending the block with addr1 at EOF not crossing page boundary */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_OHDR, (haddr_t)addr1, (hsize_t)TBLOCK_SIZE98, (hsize_t)3100); + /* Should succeed */ + if(was_extended != TRUE) TEST_ERROR + + /* Allocate 2 small meta data blocks with addr2 and addr3--will be on another meta data page */ + addr2 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE100); + addr3 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE150); + + /* The block with addr2 should be page aligned */ + /* The block with addr3 resides right next to the block with addr2 */ + if(addr2 % TBLOCK_SIZE4096) + TEST_ERROR + if(addr3 != (addr2 + TBLOCK_SIZE100)) + TEST_ERROR + + /* Free the block with addr2 */ + H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, addr2, (hsize_t)TBLOCK_SIZE100); + + /* Try extending the block with addr1 that will cross to the next page where the freed block with addr2 resides */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_OHDR, (haddr_t)addr1, (hsize_t)TBLOCK_SIZE3198, (hsize_t)TBLOCK_SIZE100); + /* Shouldn't succeed--should not cross page boundary */ + if(was_extended == TRUE) TEST_ERROR + + /* Try extending the block with addr1 into the free-space section that is big enough to fulfill the request */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_OHDR, (haddr_t)addr1, (hsize_t)TBLOCK_SIZE3198, (hsize_t)TBLOCK_SIZE50); + /* Should succeed */ + if(was_extended != TRUE) TEST_ERROR + + /* Free the block with addr1 */ + H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, addr1, (hsize_t)TBLOCK_SIZE3248); + + /* Allocate a new meta data block with addr1 */ + /* There is a page end threshold of size H5F_FILE_SPACE_PGEND_META_THRES at the end of the block */ + /* The block is right next to the threshold */ + addr1 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3286); + + /* Try extending the block into the threshold with size > H5F_FILE_SPACE_PGEND_META_THRES */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_OHDR, (haddr_t)addr1, (hsize_t)TBLOCK_SIZE3286, (hsize_t)TBLOCK_SIZE11); + /* Shouldn't succeed */ + if(was_extended == TRUE) TEST_ERROR + + /* Try extending the block into the threshold with size < H5F_FILE_SPACE_PGEND_META_THRES */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_OHDR, (haddr_t)addr1, (hsize_t)TBLOCK_SIZE3286, (hsize_t)TBLOCK_SIZE2); + /* Should succeed */ + if(was_extended != TRUE) TEST_ERROR + + /* Free the block with addr3--will merge with the remaining sections to become a page and then free the page */ + H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, addr3, (hsize_t)TBLOCK_SIZE150); + + /* Allocate a small raw data block with saddr1 */ + saddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE4086); + + /* Try extending the block crossing the page boundary */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_DRAW, (haddr_t)saddr1, (hsize_t)TBLOCK_SIZE4086, (hsize_t)TBLOCK_SIZE11); + /* Shouldn't succeed */ + if(was_extended == TRUE) TEST_ERROR + + /* Try extending the block not crossing page boundary */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_DRAW, (haddr_t)saddr1, (hsize_t)TBLOCK_SIZE4086, (hsize_t)TBLOCK_SIZE10); + /* Should succeed */ + if(was_extended != TRUE) TEST_ERROR + + /* The extended block is now "large" in size */ + /* Try extending the block */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_DRAW, (haddr_t)saddr1, (hsize_t)TBLOCK_SIZE4096, (hsize_t)TBLOCK_SIZE10); + /* Should succeed */ + if(was_extended != TRUE) TEST_ERROR + + /* Try extending the large-sized block */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_DRAW, (haddr_t)saddr1, (hsize_t)TBLOCK_SIZE4106, (hsize_t)TBLOCK_SIZE5000); + /* Should not succeed because the mis-aligned fragment in the page is in the large-sized free-space manager */ + if(was_extended == TRUE) TEST_ERROR + + /* Close the file */ + if(H5Fclose(fid) < 0) + FAIL_STACK_ERROR + + /* Close the property list */ + if(H5Pclose(fcpl) < 0) + FAIL_STACK_ERROR + + PASSED() + + } else { + SKIPPED(); + puts(" Current VFD doesn't support paged aggregation"); + } + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(fid); + H5Pclose(fcpl); + } H5E_END_TRY; + return(1); + +} /* test_page_small_try_extend() */ + +/*------------------------------------------------------------------------- + * Function: test_page_large_try_extend + * + * Purpose: To verify that extending a large block via H5MF_try_extend() + * is done properly when paged aggregation is enabled. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi; Jan 2013 + * + *------------------------------------------------------------------------- + */ +static unsigned +test_page_large_try_extend(const char *env_h5_drvr, hid_t fapl) +{ + + hid_t fid = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list */ + H5F_t *f = NULL; /* Internal file object pointer */ + haddr_t gaddr1, gaddr2, gaddr3, gaddr4; /* Addresses for large data blocks */ + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + htri_t was_extended; /* Whether the block can be extended or not */ + char filename[FILENAME_LEN]; /* Filename to use */ + + TESTING("Paged aggregation for file space: H5MF_try_extend() a large block"); + + /* Current VFD that does not support continuous address space */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + + if(contig_addr_vfd) { + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* File creation property list */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + /* Set the strategy to paged aggregation */ + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, (hsize_t)1) < 0) + FAIL_STACK_ERROR + + /* Create the file to work on */ + if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) + FAIL_STACK_ERROR + + /* Allocate a large data block with gaddr1 */ + gaddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)6000); + + /* Should be page aligned */ + if(gaddr1 % TBLOCK_SIZE4096) + TEST_ERROR + + /* Extending the block with gaddr1 at EOF to become 2 pages */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_DRAW, (haddr_t)gaddr1, (hsize_t)TBLOCK_SIZE6000, (hsize_t)TBLOCK_SIZE2192); + /* Should succeed */ + if(was_extended != TRUE) TEST_ERROR + + /* Allocate a large data block with gaddr2 */ + gaddr2 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE8000); + /* Should be page aligned */ + if(gaddr2 % TBLOCK_SIZE4096) + TEST_ERROR + + /* Try extending the block with gaddr1 */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_DRAW, (haddr_t)gaddr1, (hsize_t)TBLOCK_SIZE8192, (hsize_t)TBLOCK_SIZE50); + /* Should not succeed */ + if(was_extended == TRUE) TEST_ERROR + + /* Allocate a large data block with gaddr3 */ + gaddr3 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE8000); + /* Should be page aligned */ + if(gaddr3 % TBLOCK_SIZE4096) + TEST_ERROR + + /* Try extending the block with gaddr2--there is a free-space section big enough to fulfill the request */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_DRAW, (haddr_t)gaddr2, (hsize_t)TBLOCK_SIZE8000, (hsize_t)TBLOCK_SIZE100); + /* Should succeed */ + if(was_extended == FALSE) TEST_ERROR + + /* Try extending the block with gaddr2--there is no free-space section big enough to fulfill the request */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_DRAW, (haddr_t)gaddr2, (hsize_t)TBLOCK_SIZE8100, (hsize_t)TBLOCK_SIZE100); + /* Should not succeed */ + if(was_extended == TRUE) TEST_ERROR + + /* Try extending the block with gaddr2--there is a free-space section big enough to fulfill the request */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_DRAW, (haddr_t)gaddr2, (hsize_t)TBLOCK_SIZE8100, (hsize_t)TBLOCK_SIZE90); + /* Should succeed */ + if(was_extended == FALSE) TEST_ERROR + + /* Try extending the block with gaddr2 */ + /* There is no free-space section big enough to fulfill the request (request is < H5F_FILE_SPACE_PGEND_META_THRES) */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_DRAW, (haddr_t)gaddr2, (hsize_t)TBLOCK_SIZE8190, (hsize_t)TBLOCK_SIZE5); + /* Should not succeed */ + if(was_extended == TRUE) TEST_ERROR + + /* Allocate a large data block with gaddr4 */ + gaddr4 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5000); + /* Should be page aligned */ + if(gaddr4 % TBLOCK_SIZE4096) + TEST_ERROR + + /* Free the block with gaddr3--will merge with remaining free space to become 2 pages + section (size 2) in previous page */ + H5MF_xfree(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, gaddr3, (hsize_t)TBLOCK_SIZE8000); + + /* Try extending the block with gaddr2 crossing page boundary--there is free-space section big enough to fulfill the request */ + was_extended = H5MF_try_extend(f, H5AC_ind_read_dxpl_id, H5FD_MEM_DRAW, (haddr_t)gaddr2, (hsize_t)TBLOCK_SIZE8190, (hsize_t)TBLOCK_SIZE5); + /* Should succeed */ + if(was_extended == FALSE) TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) + FAIL_STACK_ERROR + + /* Close the property list */ + if(H5Pclose(fcpl) < 0) + FAIL_STACK_ERROR + + PASSED() + + } else { + SKIPPED(); + puts(" Current VFD doesn't support paged aggregation strategy"); + } + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(fid); + H5Pclose(fcpl); + } H5E_END_TRY; + return(1); + +} /* test_page_large_try_extend() */ + +/*------------------------------------------------------------------------- + * Function: test_page_large + * + * Purpose: To verify that allocations and de-allocations for large data + * are done properly when paged aggregation is enabled. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi; Jan 2013 + * + *------------------------------------------------------------------------- + */ +static unsigned +test_page_large(const char *env_h5_drvr, hid_t fapl) +{ + + hid_t fid = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list ID */ + H5F_t *f = NULL; /* Internal file object pointer */ + haddr_t gaddr1, gaddr2, gaddr3, gaddr4; /* Addresses for blocks */ + hbool_t contig_addr_vfd; /* Whether VFD used has a contigous address space */ + H5FS_stat_t fs_stat; /* Information for free-space manager */ + h5_stat_size_t file_size; /* File size */ + char filename[FILENAME_LEN]; /* Filename to use */ + + TESTING("Paged aggregation for file space: large allocations and de-allocations"); + + /* Current VFD that does not support continuous address space */ + contig_addr_vfd = (hbool_t)(HDstrcmp(env_h5_drvr, "split") && HDstrcmp(env_h5_drvr, "multi")); + + if(contig_addr_vfd) { + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* File creation property list */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + /* Set the strategy to paged aggregation */ + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, (hsize_t)1) < 0) + FAIL_STACK_ERROR + + /* Create the file to work on */ + if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) + FAIL_STACK_ERROR + + /* Allocate a large data block with gaddr1 */ + /* 1 page + 1904 bytes; 2192 bytes in free-space manager */ + gaddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE6000); + + /* Should be page aligned */ + if(gaddr1 % TBLOCK_SIZE4096) + TEST_ERROR + + /* Allocate a large data block with gaddr2--should be on another page */ + /* Allocate 1 page + 3904 bytes; 192 bytes in free-space manager */ + gaddr2 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE8000); + /* Should be page aligned */ + if(gaddr2 % TBLOCK_SIZE4096) + TEST_ERROR + + /* Allocate a large data block with gaddr3--should be on another page */ + /* Allocate 2 pages + 3808 bytes; 288 bytes in free-space manager */ + gaddr3 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE12000); + if(!H5F_addr_defined(gaddr3)) + TEST_ERROR + + /* Free the block with gaddr2 */ + /* Merged sections: 2192 + 8000 + 192 = 10384 */ + H5MF_xfree(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, gaddr2, (hsize_t)TBLOCK_SIZE8000); + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[H5F_MEM_PAGE_GENERIC], &fs_stat) < 0) + FAIL_STACK_ERROR + + /* Verify that the manager contains 2 free-space sections: 10384 and 288 */ + if(fs_stat.tot_sect_count != 2) + TEST_ERROR + if(fs_stat.tot_space != (10384+288)) + TEST_ERROR + + /* Allocate a large data block with gaddr4--there is a free-space section able to fulfill the request */ + /* Free-space sections: 2192 + 3192 + 288 = 5672 bytes */ + gaddr4 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5000); + + /* Should be page aligned */ + if(gaddr4 % TBLOCK_SIZE4096) + TEST_ERROR + if(gaddr4 != gaddr2) + TEST_ERROR + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[H5F_MEM_PAGE_GENERIC], &fs_stat) < 0) + FAIL_STACK_ERROR + /* Verify that that there are 3 free-space sections */ + if(fs_stat.tot_sect_count != 3) + TEST_ERROR + if(fs_stat.tot_space != (2192+3192+288)) + TEST_ERROR + + /* Free the two blocks with gaddr1 and gaddr4 */ + H5MF_xfree(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, gaddr1, (hsize_t)TBLOCK_SIZE6000); + H5MF_xfree(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, gaddr4, (hsize_t)TBLOCK_SIZE5000); + + /* Get free-space info */ + if(H5FS_stat_info(f, f->shared->fs_man[H5F_MEM_PAGE_GENERIC], &fs_stat) < 0) + FAIL_STACK_ERROR + /* Verify that that there are 2 free-space sections: 16384 (4 pages) + 288 */ + if(fs_stat.tot_sect_count != 2) + TEST_ERROR + if(fs_stat.tot_space != (16384+288)) + TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) + FAIL_STACK_ERROR + + /* Close the property list */ + if(H5Pclose(fcpl) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename, fapl)) < 0) + TEST_ERROR + + /* Verify that file size end on a page boundary */ + if(file_size % TBLOCK_SIZE4096) + TEST_ERROR + + PASSED() + + } else { + SKIPPED(); + puts(" Current VFD doesn't support paged aggregation strategy"); + } + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(fid); + } H5E_END_TRY; + return(1); + +} /* test_page_large() */ + +/*------------------------------------------------------------------------- + * Function: test_page_small + * + * Purpose: To verify allocations and de-allocations for small meta/raw data + * are done properly when paged aggregation is enabled. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi; Jan 2013 + * + *------------------------------------------------------------------------- + */ +static unsigned +test_page_small(const char *env_h5_drvr, hid_t fapl) +{ + hid_t fid = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list */ + H5F_t *f = NULL; /* Internal file object pointer */ + haddr_t addr2, addr3, addr4, addr5; /* Addresses for blocks */ + haddr_t addr9, addr10, addr11; /* Address for small meta data blocks */ + haddr_t saddr1, saddr2; /* Addresses for small raw data blocks */ + H5FS_stat_t fs_stat; /* Information for free-space manager */ + char filename[FILENAME_LEN]; /* Filename to use */ + hbool_t multi= FALSE, split = FALSE, family = FALSE; + + TESTING("Paged aggregation for file space: small allocations and de-allocations"); + + if(!HDstrcmp(env_h5_drvr, "split")) + split = TRUE; + else if(!HDstrcmp(env_h5_drvr, "multi")) + multi = TRUE; + else if(!HDstrcmp(env_h5_drvr, "family")) + family = TRUE; + + if(!multi && !split) { + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* File creation property list */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + FAIL_STACK_ERROR + + /* Set the strategy to paged aggregation */ + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, FALSE, (hsize_t)1) < 0) + FAIL_STACK_ERROR + + /* Create the file to work on */ + if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) + FAIL_STACK_ERROR + + /* Allocate 2 small meta data blocks: addr1, addr2 */ + H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + addr2 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Allocate a small raw data block with saddr1 */ + saddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + /* Should be on the second page and page aligned */ + if(saddr1 % TBLOCK_SIZE4096) + TEST_ERROR + + /* Allocate a small raw data block with saddr2 */ + saddr2 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + /* Should not be page aligned */ + if(!(saddr2 % TBLOCK_SIZE4096)) + TEST_ERROR + /* Should be next to the block with saddr1 */ + if(saddr2 != (saddr1 + TBLOCK_SIZE30)) + TEST_ERROR + + /* Allocate a small meta data block with addr3--there is no free-space section big enough to fulfill the request */ + addr3 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE4020); + /* Should be on the third page and page aligned */ + if(addr3 % TBLOCK_SIZE4096) + TEST_ERROR + + /* Allocate a small meta data block with addr4--there is a free-space section big enough to fulfill the request */ + addr4 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE80); + /* Should not be page aligned */ + if(!(addr4 % TBLOCK_SIZE4096)) + TEST_ERROR + /* Should be next to the block with addr2 */ + if(addr4 != (addr2 + TBLOCK_SIZE50)) + TEST_ERROR + + /* Allocate a small meta data block with addr5--there is a free-space section big enough to fulfill the request */ + addr5 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE40); + /* Should not be page aligned */ + if(!(addr5 % TBLOCK_SIZE4096)) + TEST_ERROR + + /* Should be next to the block with addr3 */ + if(addr5 != (addr3 + TBLOCK_SIZE4020)) + TEST_ERROR + + /* Allocate a small meta data block with addr6--taking up the remaining space in the first page */ + if(family) + H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3080); + else + H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3088); + + /* Allocate a small meta data block with addr7--taking up the remaining space in the third page */ + H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE36); + + /* Allocate 2 small meta data blocks: addr8, addr9--there is no free-space to fulfill the request */ + H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + addr9 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE80); + + /* Free the block with saddr1 and saddr2--merge with remaining section to become a page which will be returned to the large manager */ + H5MF_xfree(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, saddr1, (hsize_t)TBLOCK_SIZE30); + H5MF_xfree(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, saddr2, (hsize_t)TBLOCK_SIZE50); + + /* Verify that the large manager does contain a section with file space page size (default is 4096) */ + if(!f->shared->fs_man[H5F_MEM_PAGE_GENERIC]) + TEST_ERROR + if(H5FS_stat_info(f, f->shared->fs_man[H5F_MEM_PAGE_GENERIC], &fs_stat) < 0) + FAIL_STACK_ERROR + if(fs_stat.tot_space != TBLOCK_SIZE4096) + TEST_ERROR + + /* Allocate a small meta data block with addr10--there is a free-space section big enough to fulfill the request */ + addr10 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE3900); + /* The block should be next to the block with addr9 */ + if(addr10 != (addr9 + TBLOCK_SIZE80)) + TEST_ERROR + + /* Allocate a small meta data block with addr11 */ + /* The current free-space section is unable to fulfill the request; obtain a page from the large manager */ + addr11 = H5MF_alloc(f, H5FD_MEM_OHDR, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE80); + /* The address of the block should be the same the freed block with saddr1 */ + if(addr11 != saddr1) + TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) + FAIL_STACK_ERROR + + /* Close the property list */ + if(H5Pclose(fcpl) < 0) + FAIL_STACK_ERROR + + PASSED() + + } else { + SKIPPED(); + puts(" Current VFD doesn't support paged aggregation strategy"); + } + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(fid); + H5Pclose(fcpl); + } H5E_END_TRY; + return(1); + +} /* test_page_small() */ + +/*------------------------------------------------------------------------- + * Function: test_page_alignment + * + * Purpose: To verify the proper alignment is used when H5Pset_alignment() + * is set and paged aggregation is enabled. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Vailin Choi; Jan 2013 + * + *------------------------------------------------------------------------- + */ +static unsigned +test_page_alignment(const char *env_h5_drvr, hid_t fapl) +{ + + hid_t fid = -1; /* File ID */ + hid_t fcpl = -1; /* File creation property list ID */ + hid_t fcpl2 = -1; /* File creation property list ID */ + hid_t fapl_new = -1; /* File access property list ID */ + H5F_t *f = NULL; /* Internal file object pointer */ + haddr_t addr1, addr2; /* Addresses for small meta data blocks */ + haddr_t saddr1, saddr2; /* Addresses for small raw data blocks */ + haddr_t gaddr1, gaddr2; /* Addresses for blocks */ + char filename[FILENAME_LEN]; /* Filename to use */ + hbool_t split = FALSE, multi = FALSE; + + TESTING("Paged aggregation and H5Pset_alignment: verify proper alignment is used"); + + /* Check for split or multi driver */ + if(!HDstrcmp(env_h5_drvr, "split")) + split = TRUE; + else if(!HDstrcmp(env_h5_drvr, "multi")) + multi = TRUE; + + if(!multi && !split) { + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* + * Case 1: Verify that the alignment in use is the default file space + * page size when paged aggregation is enabled. + */ + + if((fapl_new = H5Pcopy(fapl)) < 0) TEST_ERROR + + /* The alignment to use will be the library's default file space page size */ + if(H5Pset_libver_bounds(fapl_new, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) + FAIL_STACK_ERROR + + /* Set alignment value to 16 */ + if(H5Pset_alignment(fapl_new, (hsize_t)0, (hsize_t)TEST_ALIGN16) < 0) + TEST_ERROR + + if(split || multi) { + hid_t memb_fapl; + H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; + hid_t memb_fapl_arr[H5FD_MEM_NTYPES]; + char *memb_name[H5FD_MEM_NTYPES]; + haddr_t memb_addr[H5FD_MEM_NTYPES]; + hbool_t relax; + H5FD_mem_t mt; + + /* Create fapl */ + if((memb_fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) + TEST_ERROR + + /* Set alignment */ + if(H5Pset_alignment(memb_fapl, 0, (hsize_t)TEST_ALIGN16) < 0) + TEST_ERROR + + HDmemset(memb_name, 0, sizeof memb_name); + + if(split) { + /* Set split driver with new FAPLs */ + if(H5Pset_fapl_split(fapl_new, "-m.h5", memb_fapl, "-r.h5", memb_fapl) < 0) + TEST_ERROR + + /* Get current multi settings */ + if(H5Pget_fapl_multi(fapl_new, memb_map, memb_fapl_arr, memb_name, memb_addr, &relax) < 0) + TEST_ERROR + + /* Set memb_addr aligned */ + memb_addr[H5FD_MEM_SUPER] = ((memb_addr[H5FD_MEM_SUPER] + TBLOCK_SIZE4096 - 1) / TBLOCK_SIZE4096) * TBLOCK_SIZE4096; + memb_addr[H5FD_MEM_DRAW] = ((memb_addr[H5FD_MEM_DRAW] + TBLOCK_SIZE4096 - 1) / TBLOCK_SIZE4096) * TBLOCK_SIZE4096; + + /* Set split driver with new FAPLs */ + if(H5Pset_fapl_multi(fapl_new, memb_map, memb_fapl_arr, (const char * const *)memb_name, memb_addr, relax) < 0) + TEST_ERROR + + } else { + /* Get current multi settings */ + if(H5Pget_fapl_multi(fapl_new, memb_map, NULL, memb_name, memb_addr, &relax) < 0) + TEST_ERROR + + /* Populate memb_fapl_arr */ + /* Set memb_addr aligned */ + for(mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, mt)) { + memb_fapl_arr[mt] = memb_fapl; + memb_addr[mt] = ((memb_addr[mt] + TBLOCK_SIZE4096 - 1) / TBLOCK_SIZE4096) * TBLOCK_SIZE4096; + } + + /* Set multi driver with new FAPLs */ + if(H5Pset_fapl_multi(fapl_new, memb_map, memb_fapl_arr, (const char * const *)memb_name, memb_addr, relax) < 0) + TEST_ERROR + + } /* end else */ + + /* Free memb_name */ + for(mt = H5FD_MEM_DEFAULT; mt < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, mt)) + free(memb_name[mt]); + + /* Close memb_fapl */ + if(H5Pclose(memb_fapl) < 0) + TEST_ERROR + } /* end if */ + + /* File creation property list */ + if((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) + TEST_ERROR + + /* Set the strategy to paged aggregation and persisting free space */ + /* The alignment to use will be the library's default file space page size */ + if(H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, TRUE, (hsize_t)1) < 0) + TEST_ERROR + + /* Create the file to work on */ + if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl, fapl_new)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) + TEST_ERROR + + /* Allocate 2 small raw data blocks */ + saddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + saddr2 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Should be on the second page and page aligned on 4096 (default file space page size) */ + if(saddr1 % TBLOCK_SIZE4096) + TEST_ERROR + + /* Should be next to the block with saddr1 */ + if(saddr2 != (saddr1 + TBLOCK_SIZE30)) + TEST_ERROR + + /* Allocate 2 large raw data blocks */ + gaddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5000); + gaddr2 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE8000); + + /* Should be on the 3rd page and page aligned */ + if(gaddr1 % TBLOCK_SIZE4096) + TEST_ERROR + + /* Should be on the 4th page and page aligned */ + if(gaddr2 % TBLOCK_SIZE4096) + TEST_ERROR + + /* Close the file creation property list */ + if(H5Pclose(fcpl) < 0) + TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) + TEST_ERROR + + /* + * Case 2: Verify that the alignment in use is the alignment set + * via H5Pset_alignment when paged aggregation not enabled. + */ + /* fapl_new has latest format and H5Pset_alignment set */ + /* Disable small data block mechanism */ + if(H5Pset_small_data_block_size(fapl_new, (hsize_t)0) < 0) + TEST_ERROR + /* Disable meta data block mechanism */ + if(H5Pset_meta_block_size(fapl_new, (hsize_t)0) < 0) + TEST_ERROR + + /* Create the file to work on */ + if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_new)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) + TEST_ERROR + + /* Allocate 2 small meta data blocks */ + addr1 = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + addr2 = H5MF_alloc(f, H5FD_MEM_SUPER, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Should be aligned on 16 */ + if(addr1 % TEST_ALIGN16 || addr2 % TEST_ALIGN16) + TEST_ERROR + + /* addr2 should be right next to the block with addr1 */ + if((addr1 + TBLOCK_SIZE30) % TEST_ALIGN16) + if(addr2 != (((addr1 + TBLOCK_SIZE30) / TEST_ALIGN16) + 1) * TEST_ALIGN16) + TEST_ERROR + + /* Allocate 2 small raw data blocks */ + saddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE80); + saddr2 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE100); + + /* Should be aligned on 16 */ + if(saddr1 % TEST_ALIGN16 || saddr2 % TEST_ALIGN16) + TEST_ERROR + + if(!multi && !split) { + /* saddr1 should be right next to the block with addr2 */ + if((addr2 + TBLOCK_SIZE50) % TEST_ALIGN16) + if(saddr1 != (((addr2 + TBLOCK_SIZE50) / TEST_ALIGN16) + 1) * TEST_ALIGN16) + TEST_ERROR + } + + /* saddr2 should be right next to the block with saddr1 */ + if((saddr1 + TBLOCK_SIZE80) % TEST_ALIGN16) + if(saddr2 != (((saddr1 + TBLOCK_SIZE80) / TEST_ALIGN16) + 1) * TEST_ALIGN16) + TEST_ERROR + + /* Close file */ + if(H5Fclose(fid) < 0) + TEST_ERROR + + /* + * Case 3: Verify that the alignment in use is the alignment set + * via H5Pset_alignment when paged aggregation not enabled. + */ + /* File creation property list */ + if((fcpl2 = H5Pcreate(H5P_FILE_CREATE)) < 0) + TEST_ERROR + + /* Set file space page size */ + if(H5Pset_file_space_page_size(fcpl2, (hsize_t)TBLOCK_SIZE8192) < 0) + TEST_ERROR + + /* Set strategy to H5F_FSPACE_STRATEGY_AGGR but meta/raw data block is 0 as set in fapl_new */ + if(H5Pset_file_space_strategy(fcpl2, H5F_FSPACE_STRATEGY_AGGR, FALSE, (hsize_t)1) < 0) + TEST_ERROR + + /* fapl_new has latest format, H5Pset_alignment set, and disable meta/raw block */ + if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl2, fapl_new)) < 0) + TEST_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) + TEST_ERROR + + /* Allocate 2 small raw data blocks */ + saddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE30); + saddr2 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE50); + + /* Should be aligned on 16 */ + if(saddr1 % TEST_ALIGN16) + TEST_ERROR + if(saddr2 % TEST_ALIGN16) + TEST_ERROR + + /* saddr2 should be right next to the block with saddr1 */ + if((saddr1 + TBLOCK_SIZE30) % TEST_ALIGN16) + if(saddr2 != (((saddr1 + TBLOCK_SIZE30) / TEST_ALIGN16) + 1) * TEST_ALIGN16) + TEST_ERROR + + /* Allocate a large raw data block */ + gaddr1 = H5MF_alloc(f, H5FD_MEM_DRAW, H5AC_ind_read_dxpl_id, (hsize_t)TBLOCK_SIZE5000); + + /* Should be aligned on 16 */ + if(gaddr1 % TEST_ALIGN16) + TEST_ERROR + + /* gaddr1 is right next to the block with saddr2 */ + if((saddr2 + TBLOCK_SIZE50) % TEST_ALIGN16) + if(gaddr1 != (((saddr2 + TBLOCK_SIZE50) / TEST_ALIGN16) + 1) * TEST_ALIGN16) + TEST_ERROR + + /* There is no free-space manager involved for H5F_FSPACE_STRATEGY_AGGR strategy */ + if(f->shared->fs_man[H5FD_MEM_DRAW] || f->shared->fs_man[H5FD_MEM_SUPER]) + TEST_ERROR + + /* Closing */ + if(H5Fclose(fid) < 0) + TEST_ERROR + if(H5Pclose(fcpl2) < 0) + TEST_ERROR + if(H5Pclose(fapl_new) < 0) + TEST_ERROR + + PASSED() + + } else { + SKIPPED(); + puts(" Current VFD doesn't support persisting free-space or paged aggregation strategy"); + } + + return(0); + +error: + H5E_BEGIN_TRY { + H5Fclose(fid); + H5Pclose(fcpl); + H5Pclose(fapl_new); + } H5E_END_TRY; + return(1); + +} /* test_page_alignment() */ + +int +main(void) +{ + hid_t fapl = -1; /* File access property list for data files */ + hid_t new_fapl = -1; /* File access property list for alignment & aggr setting */ + unsigned nerrors = 0; /* Cumulative error count */ + test_type_t curr_test; /* Current test being worked on */ + const char *env_h5_drvr; /* File Driver value from environment */ + + /* Get the VFD to use */ + env_h5_drvr = HDgetenv("HDF5_DRIVER"); + if(env_h5_drvr == NULL) + env_h5_drvr = "nomatch"; + + h5_reset(); + + fapl = h5_fileaccess(); + + /* Make a copy of the FAPL before adjusting the alignment */ + if((new_fapl = H5Pcopy(fapl)) < 0) TEST_ERROR + /* For old library format--interaction with file allocation */ + nerrors += test_mf_eoa(env_h5_drvr, fapl); + nerrors += test_mf_eoa_shrink(env_h5_drvr, fapl); + nerrors += test_mf_eoa_extend(env_h5_drvr, fapl); + + /* For old library format */ + nerrors += test_dichotomy(new_fapl); + + /* For old library format--interaction with free-space manager */ + nerrors += test_mf_fs_start(fapl); + nerrors += test_mf_fs_alloc_free(fapl); + nerrors += test_mf_fs_extend(fapl); + nerrors += test_mf_fs_absorb(env_h5_drvr, fapl); + + /* For old library format--interaction with meta/sdata aggregator */ + nerrors += test_mf_aggr_alloc1(env_h5_drvr, fapl); + nerrors += test_mf_aggr_alloc2(env_h5_drvr, fapl); + nerrors += test_mf_aggr_alloc3(env_h5_drvr, fapl); + nerrors += test_mf_aggr_alloc4(env_h5_drvr, fapl); + nerrors += test_mf_aggr_alloc5(env_h5_drvr, fapl); + nerrors += test_mf_aggr_alloc6(env_h5_drvr, fapl); + nerrors += test_mf_aggr_alloc7(env_h5_drvr, fapl); + nerrors += test_mf_aggr_extend(env_h5_drvr, fapl); + nerrors += test_mf_aggr_absorb(env_h5_drvr, fapl); + + /* For old library format--tests for alignment */ + for(curr_test = TEST_NORMAL; curr_test < TEST_NTESTS; H5_INC_ENUM(test_type_t, curr_test)) { + + switch(curr_test) { + case TEST_NORMAL: /* set alignment = 1024 */ + if(H5Pset_alignment(new_fapl, (hsize_t)0, (hsize_t)TEST_ALIGN1024) < 0) + TEST_ERROR + break; + + case TEST_AGGR_SMALL: /* set alignment = 4096 */ + if(H5Pset_alignment(new_fapl, (hsize_t)0, (hsize_t)TEST_ALIGN4096) < 0) + TEST_ERROR + break; + + case TEST_NTESTS: + default: + TEST_ERROR; + break; + } /* end switch */ + + nerrors += test_mf_align_eoa(env_h5_drvr, fapl, new_fapl); + nerrors += test_mf_align_fs(env_h5_drvr, fapl, new_fapl); + nerrors += test_mf_align_alloc1(env_h5_drvr, fapl, new_fapl); + nerrors += test_mf_align_alloc2(env_h5_drvr, fapl, new_fapl); + nerrors += test_mf_align_alloc3(env_h5_drvr, fapl, new_fapl); + nerrors += test_mf_align_alloc4(env_h5_drvr, fapl, new_fapl); + nerrors += test_mf_align_alloc5(env_h5_drvr, fapl, new_fapl); + nerrors += test_mf_align_alloc6(env_h5_drvr, fapl, new_fapl); + } /* end for */ + + /* For old and new format--interaction with temporary file space allocation */ + nerrors += test_mf_tmp(env_h5_drvr, fapl, FALSE); + nerrors += test_mf_tmp(env_h5_drvr, fapl, TRUE); + + /* For old and new format--free-space merge/shrunk away */ + + /* Temporary: modify to skip testing for multi/split driver: + fail file create when persisting free-space or using paged aggregation strategy */ + nerrors += test_mf_fs_gone(env_h5_drvr, fapl, FALSE); + nerrors += test_mf_fs_gone(env_h5_drvr, fapl, TRUE); + + /* Temporary: modify to skip testing multi/split driver: + fail file create when persisting free-space or using paged aggregation strategy */ + nerrors += test_mf_strat_thres_gone(env_h5_drvr, fapl, FALSE); + nerrors += test_mf_strat_thres_gone(env_h5_drvr, fapl, TRUE); + + /* For old and new format--persisting free-space */ + + /* Temporary: Modify to skip testing for multi/split driver: + fail file create when persisting free-space or using paged aggregation strategy */ + nerrors += test_mf_fs_persist(env_h5_drvr, fapl, FALSE); + nerrors += test_mf_fs_persist(env_h5_drvr, fapl, TRUE); + + /* Temporary: modify to skip testing for multi/split driver: + fail file create when persisting free-space or using paged aggregation strategy */ + nerrors += test_mf_strat_thres_persist(env_h5_drvr, fapl, FALSE); + nerrors += test_mf_strat_thres_persist(env_h5_drvr, fapl, TRUE); + + /* Temporary skipped for multi/split drivers: + fail file create when persisting free-space or using paged aggregation strategy */ +#ifdef PB_OUT + /* Tests specific for multi and split files--persisting free-space */ + nerrors += test_mf_fs_persist_split(); + nerrors += test_mf_fs_persist_multi(); +#endif + + /* + * Tests specific for file space paging + */ + /* Temporary: The following 7 tests are modified to skip testing for multi/split driver: + fail file create when persisting free-space or using paged aggregation strategy */ + nerrors += test_page_small(env_h5_drvr, fapl); + nerrors += test_page_large(env_h5_drvr, fapl); + nerrors += test_page_large_try_extend(env_h5_drvr, fapl); + nerrors += test_page_small_try_extend(env_h5_drvr, fapl); + nerrors += test_page_try_shrink(env_h5_drvr, fapl); + nerrors += test_page_alloc_xfree(env_h5_drvr, fapl); /* can handle multi/split */ + nerrors += test_page_alignment(env_h5_drvr, fapl); /* can handle multi/split */ + + /* tests for specific bugs */ + nerrors += test_mf_bug1(env_h5_drvr, fapl); + + if(H5Pclose(new_fapl) < 0) + FAIL_STACK_ERROR + h5_cleanup(FILENAME, fapl); + + if(nerrors) + goto error; + puts("All free-space manager tests for file memory passed."); + + return(0); + +error: + puts("*** TESTS FAILED ***"); + H5E_BEGIN_TRY { + H5Pclose(fapl); + H5Pclose(new_fapl); + } H5E_END_TRY; + return(1); +} /* main() */ + |