diff options
Diffstat (limited to 'test/freespace.c')
-rw-r--r-- | test/freespace.c | 2805 |
1 files changed, 2805 insertions, 0 deletions
diff --git a/test/freespace.c b/test/freespace.c new file mode 100644 index 0000000..c786ebb --- /dev/null +++ b/test/freespace.c @@ -0,0 +1,2805 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* + * Tests for free-space manager + */ +#include "h5test.h" + +#define H5FS_PACKAGE +#define H5FS_TESTING +#include "H5FSpkg.h" /* Free space manager */ + + +/* Other private headers that this test requires */ +#define H5F_PACKAGE +#include "H5Fpkg.h" +#include "H5FLprivate.h" +#include "H5Iprivate.h" +#include "H5Vprivate.h" + +#define FILENAME_LEN 1024 + +#define TEST_FSPACE_CLIENT_ID 2 +#define TEST_FSPACE_SECT_TYPE 0 +#define TEST_FSPACE_SECT_TYPE_NEW 1 +#define TEST_FSPACE_SECT_TYPE_NONE 2 + +#define TEST_FSPACE_SHRINK 80 +#define TEST_FSPACE_EXPAND 120 +#define TEST_MAX_SECT_SIZE (64 * 1024) +#define TEST_MAX_INDEX 32 + +#define TEST_SECT_ADDR60 60 +#define TEST_SECT_ADDR70 70 +#define TEST_SECT_ADDR80 80 +#define TEST_SECT_ADDR100 100 +#define TEST_SECT_ADDR150 150 +#define TEST_SECT_ADDR200 200 +#define TEST_SECT_ADDR300 300 + +#define TEST_SECT_SIZE5 5 +#define TEST_SECT_SIZE10 10 +#define TEST_SECT_SIZE15 15 +#define TEST_SECT_SIZE20 20 +#define TEST_SECT_SIZE30 30 +#define TEST_SECT_SIZE40 40 +#define TEST_SECT_SIZE50 50 +#define TEST_SECT_SIZE80 80 + +#define FSPACE_THRHD_DEF 1 /* Default: no alignment threshold */ +#define FSPACE_ALIGN_DEF 1 /* Default: no alignment */ + +const char *FILENAME[] = { + "frspace", + NULL +}; + +typedef struct frspace_state_t { + hsize_t tot_space; /* Total amount of space tracked */ + hsize_t tot_sect_count; /* Total # of sections tracked */ + hsize_t serial_sect_count; /* # of serializable sections tracked */ + hsize_t ghost_sect_count; /* # of un-serializable sections tracked */ +} frspace_state_t; + +haddr_t g_eoa=0; +static haddr_t TEST_get_eoa(void); +static void TEST_set_eoa(haddr_t); + +/* + * TEST client + */ +typedef struct TEST_free_section_t { + H5FS_section_info_t sect_info; /* Free space section information (must be first in struct) */ +} TEST_free_section_t; + +H5FL_DEFINE(TEST_free_section_t); + + +static herr_t TEST_sect_init_cls(H5FS_section_class_t *, void *); +static herr_t TEST_sect_free(H5FS_section_info_t *_sect); +static herr_t TEST_sect_can_merge(const H5FS_section_info_t *, const H5FS_section_info_t *, void UNUSED *); +static herr_t TEST_sect_merging(H5FS_section_info_t *, H5FS_section_info_t *, void UNUSED *); +static herr_t TEST_sect_can_shrink(const H5FS_section_info_t *, void *); +static herr_t TEST_sect_shrinking(H5FS_section_info_t **, void *); + +H5FS_section_class_t TEST_FSPACE_SECT_CLS[1] = {{ + TEST_FSPACE_SECT_TYPE, /* Section type */ + 0, /* Extra serialized size */ + H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ + TEST_sect_init_cls, /* Initialize section class */ + NULL, /* Terminate section class */ + + /* Object methods */ + NULL, /* Add section */ + NULL, /* Serialize section */ + NULL, /* Deserialize section */ + TEST_sect_can_merge, /* Can sections merge? */ + TEST_sect_merging, /* Merge sections */ + TEST_sect_can_shrink, /* Can section shrink container?*/ + TEST_sect_shrinking, /* Shrink container w/section */ + TEST_sect_free, /* Free section */ + NULL, /* Check validity of section */ + NULL, /* Split section node for alignment */ + NULL, /* Dump debugging for section */ +}}; + +H5FS_section_class_t TEST_FSPACE_SECT_CLS_NEW[1] = {{ + TEST_FSPACE_SECT_TYPE_NEW, /* Section type */ + 0, /* Extra serialized size */ + H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ + TEST_sect_init_cls, /* Initialize section class */ + NULL, /* Terminate section class */ + + /* Object methods */ + NULL, /* Add section */ + NULL, /* Serialize section */ + NULL, /* Deserialize section */ + TEST_sect_can_merge, /* Can sections merge? */ + TEST_sect_merging, /* Merge sections */ + NULL, /* Can section shrink container?*/ + NULL, /* Shrink container w/section */ + TEST_sect_free, /* Free section */ + NULL, /* Check validity of section */ + NULL, /* Split section node for alignment */ + NULL, /* Dump debugging for section */ +}}; + +H5FS_section_class_t TEST_FSPACE_SECT_CLS_NOINIT[1] = {{ + TEST_FSPACE_SECT_TYPE_NONE, /* Section type */ + 0, /* Extra serialized size */ + H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */ + NULL, /* Class private info */ + + /* Class methods */ + NULL, /* Initialize section class */ + NULL, /* Terminate section class */ + + /* Object methods */ + NULL, /* Add section */ + NULL, /* Serialize section */ + NULL, /* Deserialize section */ + TEST_sect_can_merge, /* Can sections merge? */ + TEST_sect_merging, /* Merge sections */ + NULL, /* Can section shrink container?*/ + NULL, /* Shrink container w/section */ + TEST_sect_free, /* Free section */ + NULL, /* Check validity of section */ + NULL, /* Split section node for alignment */ + NULL, /* Dump debugging for section */ +}}; + +const H5FS_section_class_t *test_classes[] = { + TEST_FSPACE_SECT_CLS, + TEST_FSPACE_SECT_CLS_NEW, + TEST_FSPACE_SECT_CLS_NOINIT +}; + + +static void init_cparam(H5FS_create_t *); +static void init_sect_node(TEST_free_section_t *, haddr_t, hsize_t, unsigned, H5FS_section_state_t); +static int check_stats(const H5FS_t *, const frspace_state_t *); + +#define NUM_SECTIONS 1000 + +/* User data for free space section iterator callback */ +typedef struct { + hsize_t tot_size; + hsize_t tot_sect_count; +} TEST_iter_ud_t; + +static herr_t TEST_sects_cb(const H5FS_section_info_t *_sect, void *_udata); + + +/* + * Tests + */ +static int test_fs_create(hid_t); +static int test_fs_sect_add(hid_t); +static int test_fs_sect_merge(hid_t); +static int test_fs_sect_shrink(hid_t); +static int test_fs_sect_find(hid_t); +static int test_fs_sect_change_class(hid_t); +static int test_fs_sect_extend(hid_t); +static int test_fs_sect_iterate(hid_t); + +/* + * free-space section routines for client TEST + */ +static herr_t +TEST_sect_init_cls(H5FS_section_class_t *cls, void *_udata) +{ + herr_t ret_value = SUCCEED; /* Return value */ + unsigned *init_flags; + + /* Check arguments. */ + HDassert(cls); + HDassert(_udata); + + init_flags = (unsigned *)_udata; + cls->flags |= *init_flags; + + return(ret_value); +} /* TEST_sect_init_cls() */ + +/* + * Check if the two sections can be merged: + * true if second section adjoins the first section + */ +static herr_t +TEST_sect_can_merge(const H5FS_section_info_t *_sect1, + const H5FS_section_info_t *_sect2, void UNUSED *_udata) +{ + const TEST_free_section_t *sect1 = (const TEST_free_section_t *)_sect1; + const TEST_free_section_t *sect2 = (const TEST_free_section_t *)_sect2; + htri_t ret_value; /* Return value */ + + /* Check arguments. */ + HDassert(sect1); + HDassert(sect2); + HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */ + HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr)); + + /* Check if second section adjoins first section */ + ret_value = H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr); + + return(ret_value); +} /* TEST_sect_can_merge() */ + +/* + * Merge the two sections (second section is merged into the first section) + */ +static herr_t +TEST_sect_merging(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2, + void UNUSED *_udata) +{ + TEST_free_section_t *sect1 = (TEST_free_section_t *)_sect1; + TEST_free_section_t *sect2 = (TEST_free_section_t *)_sect2; + herr_t ret_value = SUCCEED; /* Return value */ + + /* Check arguments. */ + HDassert(sect1); + HDassert((sect1->sect_info.type == TEST_FSPACE_SECT_TYPE) || + (sect1->sect_info.type == TEST_FSPACE_SECT_TYPE_NEW) || + (sect1->sect_info.type == TEST_FSPACE_SECT_TYPE_NONE)); + HDassert(sect2); + HDassert((sect2->sect_info.type == TEST_FSPACE_SECT_TYPE) || + (sect2->sect_info.type == TEST_FSPACE_SECT_TYPE_NEW) || + (sect2->sect_info.type == TEST_FSPACE_SECT_TYPE_NONE)); + HDassert(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr)); + + /* Add second section's size to first section */ + sect1->sect_info.size += sect2->sect_info.size; + + /* Get rid of second section */ + if(TEST_sect_free((H5FS_section_info_t *)sect2) < 0) + TEST_ERROR +error: + return(ret_value); +} /* TEST_sect_merging() */ + +/* + * Free the section + */ +static herr_t +TEST_sect_free(H5FS_section_info_t *_sect) +{ + TEST_free_section_t *sect = (TEST_free_section_t *)_sect; + + /* Release the section */ + H5FL_FREE(TEST_free_section_t, sect); + + return(0); +} /* TEST_sect_free() */ + +/* + * Determine if the section can be shrunk and set _udata accordingly + * if _udata passed in is NULL, return FALSE + * Otherwise: + * if section's address+size is the end of file, return TRUE + * otherwise return FALSE + */ +static herr_t +TEST_sect_can_shrink(const H5FS_section_info_t *_sect, void *_udata) +{ + unsigned *can_shrink = (unsigned *)_udata; + const TEST_free_section_t *sect = (const TEST_free_section_t *)_sect; + haddr_t end, eoa; + + if (can_shrink == NULL) + return(FALSE); + + end = sect->sect_info.addr + sect->sect_info.size; + eoa = TEST_get_eoa(); + + if (end == eoa) + *can_shrink = TRUE; + else + *can_shrink = FALSE; + return(*can_shrink); + +} /* TEST_sect_can_shrink() */ + +/* + * Shrink the section + */ +static herr_t +TEST_sect_shrinking(H5FS_section_info_t **_sect, void *_udata) +{ + TEST_free_section_t **sect = (TEST_free_section_t **)_sect; + unsigned *can_shrink = (unsigned *)_udata; + + /* address of the section is faked, so, doesn't need to do anything */ + /* just free the section node */ + if (*can_shrink) { + if (TEST_sect_free((H5FS_section_info_t *)*sect) < 0) + TEST_ERROR + *sect = NULL; + return(TRUE); + } + +error: + return(FALSE); +} + + +/* + * iteration callback + */ +static herr_t +TEST_sects_cb(const H5FS_section_info_t *_sect, void *_udata) +{ + const TEST_free_section_t *sect = (const TEST_free_section_t *)_sect; + TEST_iter_ud_t *udata = (TEST_iter_ud_t *)_udata; + herr_t ret_value = SUCCEED; /* Return value */ + + HDassert(sect); + HDassert(udata); + + udata->tot_size += sect->sect_info.size; + udata->tot_sect_count += 1; + + return(ret_value); +} + +/* supporting routine for shrinking */ +static haddr_t +TEST_get_eoa(void) +{ + return(g_eoa); +} + +/* supporting routine for shrinking */ +static void +TEST_set_eoa(haddr_t val) +{ + g_eoa = val; +} + +/* + * Initialize creation parameter structure for TEST client + */ +static void +init_cparam(H5FS_create_t *cparam) +{ + HDmemset(cparam, 0, sizeof(H5FS_create_t)); + + /* Set the free space creation parameters */ + cparam->shrink_percent = TEST_FSPACE_SHRINK; + cparam->expand_percent = TEST_FSPACE_EXPAND; + cparam->max_sect_size = TEST_MAX_SECT_SIZE; + cparam->max_sect_addr = TEST_MAX_INDEX; + +} /* init_cparam() */ + +/* + * Initialize free space section node + */ +static void +init_sect_node(TEST_free_section_t *sect_node, haddr_t addr, hsize_t size, unsigned type, H5FS_section_state_t state) +{ + sect_node->sect_info.addr = addr; + sect_node->sect_info.size = size; + sect_node->sect_info.type = type; + sect_node->sect_info.state = state; +} /* init_sect_node() */ + +/* + * Verify statistics for the free-space manager + */ +static int +check_stats(const H5FS_t *frsp, const frspace_state_t *state) +{ + H5FS_stat_t frspace_stats; /* Statistics about the heap */ + + /* Get statistics for heap and verify they are correct */ + if(H5FS_stat_info(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() */ + +/* + * TESTS for free-space manager + */ + +/* + * To verify the creation, close, reopen and deletion of the free-space manager + */ +static int +test_fs_create(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr; /* address of free space */ + h5_stat_size_t file_size, empty_size; /* File size */ + frspace_state_t state; /* State of free space*/ + H5FS_create_t cparam, test_cparam; /* creation parameters */ + size_t nclasses; + unsigned init_flags=0; + + TESTING("the creation/close/reopen/deletion of the 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 + + /* Close file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file w/empty heap*/ + if((empty_size = h5_get_file_size(filename)) < 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 = H5I_object(file))) + FAIL_STACK_ERROR + + /* initialize creation parameters for free-space manager */ + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + if (frsp->nclasses != nclasses) + TEST_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + if(check_stats(frsp, &state)) + TEST_ERROR + + HDmemset(&test_cparam, 0, sizeof(H5FS_create_t)); + if(H5FS_get_cparam_test(frsp, &test_cparam) < 0) + FAIL_STACK_ERROR + if (H5FS_cmp_cparam_test(&cparam, &test_cparam)) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* reopen the free-space manager */ + if(NULL == (frsp = H5FS_open(f, H5P_DATASET_XFER_DEFAULT, fs_addr, + nclasses, test_classes, NULL, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + if (frsp->nclasses != nclasses) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of the file */ + if((file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + /* Verify the file is the correct size */ + if(file_size != empty_size) + TEST_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_fs_create() */ + + +/* + * Test 1: + * Create free-space manager + * Add section A via H5FS_sect_add() with H5FS_ADD_RETURNED_SPACE + * Close the free-space manager + * Result: section A is serialized to the file + * + * Test 2: + * Create free-space manager with H5FS_CLS_GHOST_OBJ section class setting + * Add section A via H5FS_sect_add() with H5FS_ADD_RETURNED_SPACE + * Close the free-space manager + * Result: section A is not serialized to the file + * + * Test 3: + * Add section A via H5FS_sect_add() to allow shrinking with H5FS_ADD_RETURNED_SPACE + * Set EOF to be the ending address of section A + * Result: H5FS_sect_add() will shrink section A + * + * Test 4: + * Add section A via H5FS_sect_add() to allow shrinking with H5FS_ADD_DESERIALIZING + * Set EOF to be the ending address of section A + * Result: H5FS_sect_add() will not shrink section A + * + */ +static int +test_fs_sect_add(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node; + unsigned init_flags=0; + h5_stat_size_t file_size=0, tmp_file_size=0, fr_meta_size=0; + unsigned can_shrink=FALSE; + + TESTING("adding a section via H5FS_sect_add() to free-space: test 1"); + + 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 w/empty heap*/ + if((file_size = h5_get_file_size(filename)) < 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 = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + if(NULL == (sect_node = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE20, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + fr_meta_size = H5FS_HEADER_SIZE(f) + H5FS_SINFO_PREFIX_SIZE(f); + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file w/empty heap*/ + if((tmp_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + if (tmp_file_size <= (file_size+fr_meta_size)) + TEST_ERROR + + PASSED() + + TESTING("adding a section via H5FS_sect_add() to free-space with H5FS_CLS_GHOST_OBJ: test 2"); + + /* Get the size of a file w/empty heap*/ + if((file_size = h5_get_file_size(filename)) < 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 = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = H5FS_CLS_GHOST_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* Create free list section node */ + if(NULL == (sect_node = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE20, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node, + 0, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node->sect_info.size; + state.tot_sect_count += 1; + state.ghost_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + fr_meta_size = H5FS_HEADER_SIZE(f); + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + /* Get the size of a file w/empty heap*/ + if((tmp_file_size = h5_get_file_size(filename)) < 0) + TEST_ERROR + + if (tmp_file_size != (file_size+fr_meta_size)) + TEST_ERROR + + PASSED() + + TESTING("adding a section via H5FS_sect_add() to free-space: test 3"); + + /* 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 w/empty heap*/ + if((file_size = h5_get_file_size(filename)) < 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 = H5I_object(file))) + FAIL_STACK_ERROR + + TEST_set_eoa((haddr_t)TEST_SECT_ADDR150); /* set end of file address for shrinking */ + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = 0; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + if(NULL == (sect_node = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + /* + * Add section A + */ + init_sect_node(sect_node, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + /* nothing in free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("adding a section via H5FS_sect_add() to free-space: test 4"); + + /* 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 w/empty heap*/ + if((file_size = h5_get_file_size(filename)) < 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 = H5I_object(file))) + FAIL_STACK_ERROR + + TEST_set_eoa((haddr_t)TEST_SECT_ADDR150); /* set end of file address for shrinking */ + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = 0; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + if(NULL == (sect_node = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + /* + * Add section A + */ + init_sect_node(sect_node, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node, + H5FS_ADD_DESERIALIZING, &can_shrink)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_fs_sect_add() */ + + +/* + * To verify the finding of a section with the requested-size from free-space + * + * Test 1: Free-space is empty and is not able to fulfill the requested-size + * Set up: free-space is started up but is empty + * + * Test 2: Add a section and find the section whose size is equal to the requested-size + * Set up: Add section A whose size is less than requested-size + * Add section B whose size is the same as requested-size with addr=b + * Add section C whose size is the same as requested-size with addr=c > b + * Add section D whose size is greater than requested-size + * + * Test 3: Add a section and find the section whose size is > requested-size + * Set up: Add section A whose size is less than requested-size + * Add section B whose size is greater than requested-size + * + * Test 4: Add a section but the section is not able to fulfill the requested-size + * Set up: Add section A whose size is less than requested-size + * + */ +static int +test_fs_sect_find(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node1, *sect_node2, *sect_node3, *sect_node4; + TEST_free_section_t *node; + htri_t node_found = FALSE; + unsigned init_flags=0; + + TESTING("H5FS_sect_find(): free-space is empty"); + + /* Set the filename to use for this test (dependent on fapl) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + + if(check_stats(frsp, &state)) + TEST_ERROR + + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE30, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + PASSED() + + TESTING("H5FS_sect_find() a section equal to requested-size from free-space"); + + /* reopen the free-space manager */ + if(NULL == (frsp = H5FS_open(f, H5P_DATASET_XFER_DEFAULT, fs_addr, nclasses, + test_classes, NULL, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + if (frsp->nclasses != nclasses) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + + /* + * Add section C + */ + if(NULL == (sect_node3 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node3, (haddr_t)(TEST_SECT_ADDR200), (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node3->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section D + */ + if(NULL == (sect_node4 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node4, (haddr_t)TEST_SECT_ADDR300, (hsize_t)TEST_SECT_SIZE80, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node4, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node4->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE50, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR100) || (node->sect_info.size != TEST_SECT_SIZE50)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* remove sections A, C and D */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1) < 0) + FAIL_STACK_ERROR + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3) < 0) + FAIL_STACK_ERROR + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node4) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + PASSED() + + TESTING("H5FS_sect_find() a section greater than requested-size from free-space"); + + /* reopen the free-space manager */ + if(NULL == (frsp = H5FS_open(f, H5P_DATASET_XFER_DEFAULT, fs_addr, nclasses, + test_classes, NULL, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + if (frsp->nclasses != nclasses) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR200, (hsize_t)TEST_SECT_SIZE80, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE50, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + if ((node->sect_info.addr != TEST_SECT_ADDR200) || (node->sect_info.size < TEST_SECT_SIZE50)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* remove sections A */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + PASSED() + + TESTING("H5FS_sect_find(): cannot find a section with requested-size from free-space"); + + /* reopen the free-space manager */ + if(NULL == (frsp = H5FS_open(f, H5P_DATASET_XFER_DEFAULT, fs_addr, nclasses, + test_classes, NULL, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + if (frsp->nclasses != nclasses) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE50, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* remove sections A */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_fs_sect_find() */ + + +/* + * To verify that sections are merged when adding sections to free-space + * + * Test 1: + * Set up: + * H5FS_CLS_SEPAR_OBJ (cls->flags) is not set + * H5FS_ADD_RETURNED_SPACE is passed to H5FS_sect_add() + * + * Add sections C, B, A & D that can be merged together + * + * Test 2: + * Set up: + * H5FS_CLS_SEPAR_OBJ (cls->flags) is set + * H5FS_ADD_RETURNED_SPACE is passed to H5FS_sect_add() + * + * Add sections A & B that can be merged together but cannot do so because H5FS_CLS_SEPAR_OBJ flag is set + * + * Test 3: + * Set up: + * H5FS_CLS_SEPAR_OBJ (cls->flags) is not set + * H5FS_ADD_RETURNED_SPACE is passed to H5FS_sect_add() + * + * Add 4 sections that adjoin each other as follows: + * section A is of section class type A + * section B is of section class type B + * section C is of section class type B + * section D is of section class type A + * Sections B & C are merged together but not section A nor D because: + * sections B & C are merged because of the same section class type + * section A cannot be merged with the merged section of B & C because of different section class type + * section D cannot be merged with the merged section of B & C because of different section class type + */ +static int +test_fs_sect_merge(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node1=NULL, *sect_node2=NULL, *sect_node3=NULL, *sect_node4=NULL; + unsigned init_flags=0; + htri_t node_found = FALSE; + TEST_free_section_t *node; + + TESTING("the merge of sections when H5FS_sect_add() to free-space: test 1"); + + /* + * 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 + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section C + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_SECT_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* section B & C are merged */ + state.tot_space += TEST_SECT_SIZE30; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node3 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node3, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE10, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* section A is merged with the merged section of B & C */ + state.tot_space += TEST_SECT_SIZE10; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section D + */ + if(NULL == (sect_node4 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node4, (haddr_t)TEST_SECT_ADDR150, (hsize_t)TEST_SECT_SIZE80, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node4, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* section D is merged with the merged section of A & B & C */ + state.tot_space += TEST_SECT_SIZE80; + + if(check_stats(frsp, &state)) + TEST_ERROR + + + /* should be able to find the merged section of A, B, C & D */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE10+TEST_SECT_SIZE30+TEST_SECT_SIZE50+TEST_SECT_SIZE80), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + if ((node->sect_info.addr != TEST_SECT_ADDR60) || + (node->sect_info.size != (TEST_SECT_SIZE10+TEST_SECT_SIZE30+TEST_SECT_SIZE50+TEST_SECT_SIZE80))) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + /* + * TEST 2 + */ + TESTING("the merge of sections when H5FS_sect_add() to free-space: test 2"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = H5FS_CLS_SEPAR_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_SECT_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* section A & B are not merged because H5FS_CLS_SEPAR_OBJ is set */ + state.tot_space += TEST_SECT_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* should not be able to find the merged section of A & B */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE30+TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* remove section A from free-space */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1) < 0) + FAIL_STACK_ERROR + /* remove section B from free-space */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + /* + * TEST 3 + */ + TESTING("the merge of sections when H5FS_sect_add() to free-space: test 3"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = 0; /* reset */ + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE10, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_SECT_SIZE10; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE_NEW, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* sections A & B are not merged because H5FS_CLS_MERGE_SYM is set & section class type is different */ + state.tot_space += TEST_SECT_SIZE30; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section C + */ + if(NULL == (sect_node3 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node3, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE_NEW, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* sections B & C are merged because H5FS_CLS_MERGE_SYM is set & section class type is the same */ + state.tot_space += TEST_SECT_SIZE50; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section D + */ + if(NULL == (sect_node4 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node4, (haddr_t)TEST_SECT_ADDR150, (hsize_t)TEST_SECT_SIZE80, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node4, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* + * section D is not merged with the merged section of B & C because + * H5FS_CLS_MERGE_SYM is set and section class type is different + */ + state.tot_space += TEST_SECT_SIZE80; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* should not be able to find a merged section of A, B, C & D */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE10+TEST_SECT_SIZE30+TEST_SECT_SIZE50+TEST_SECT_SIZE80), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* should be able to find the merged section of B & C */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE30+TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR70) || + (node->sect_info.size != (TEST_SECT_SIZE30+TEST_SECT_SIZE50))) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* should be able to find section A */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE10), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR60) || (node->sect_info.size != TEST_SECT_SIZE10)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* should be able to find section D */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE80), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR150) || (node->sect_info.size != TEST_SECT_SIZE80)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_fs_sect_merge() */ + +/* + * To verify that sections are shrunk when adding sections to free-space + * + * Test 1: + * Set EOF to be the ending address of section A + * H5FS_CLS_SEPAR_OBJ (cls->flags) is not set when creating free-space manager + * Add section A to allow shrinking but is not shrunk because its section class type + * TEST_FSPACE_SECT_TYPE_NEW does not define "can_shrink" + * Result:section A is not shrunk and section A is still in free-space + * + * Re-add section A to allow shrinking and with section class type TEST_FSPACE_SECT_TYPE + * that defines "can_shrink" + * Result:section A is shrunk and there is nothing in free-space + * + * Test 2: + * Set EOF to be greater than the ending address of section A + * Set H5FS_CLS_SEPAR_OBJ (cls->flags) when creating free-space manager + * + * Add section A to allow shrinking but is not shrunk because it is not at EOF, + * and section A is not on the merge list due to H5FS_CLS_SEPAR_OBJ + * Add section B to allow shrinking and whose ending address is the same as eof. + * Section B is not merged with section A because of H5FS_CLS_SEPAR_OBJ but it is shrunk + * Result: section A is still in free-space + * + * Test 3: + * Set EOF to be greater than the ending address of section A + * H5FS_CLS_SEPAR_OBJ (cls->flags) is not set when creating free-space manager + * + * Add section A to allow shrinking but is not shrunk because it is not at EOF, + * and section A is on the merge list + * Add section B to allow shrinking and whose ending address is the same as eof. + * Section B is merged with section A and then shrunk. + * Result: free-space should be empty + */ +static int +test_fs_sect_shrink(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node1=NULL, *sect_node2=NULL; + unsigned init_flags=0; + unsigned can_shrink=FALSE; + htri_t node_found = FALSE; + TEST_free_section_t *node; + + TESTING("shrinking of sections when H5FS_sect_add() to free-space: 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 + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + TEST_set_eoa((haddr_t)TEST_SECT_ADDR150); /* set end of file address for shrinking */ + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A that allow shrinking but its section class type does not define "can_shrink" + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE_NEW, H5FS_SECT_LIVE); + + can_shrink = FALSE; + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* section A should still be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR100) || (node->sect_info.size != TEST_SECT_SIZE50)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* + * Re-add section A that allow shrinking and its section class type defines "can_shrink" + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + can_shrink = FALSE; + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + /* should have nothing in free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* section A should not be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + + TESTING("shrinking of sections when H5FS_sect_add() to free-space: test 2"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + TEST_set_eoa((haddr_t)TEST_SECT_ADDR150); /* set end of file address for shrinking */ + + /* does not allow merging */ + init_flags = H5FS_CLS_SEPAR_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE20, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + /* free-space should be the same since section B is shrunk */ + if(check_stats(frsp, &state)) + TEST_ERROR + + /* section B should not be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + if(check_stats(frsp, &state)) + TEST_ERROR + + + /* section A should still be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE20), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (!node_found) TEST_ERROR + + if ((node->sect_info.addr != TEST_SECT_ADDR80) || (node->sect_info.size != TEST_SECT_SIZE20)) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + TESTING("shrinking of sections when H5FS_sect_add() to free-space: test 3"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + TEST_set_eoa((haddr_t)TEST_SECT_ADDR150); /* set end of file address for shrinking */ + + init_flags = 0; /* reset */ + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, &can_shrink)) + FAIL_STACK_ERROR + + /* section A & B are merged and then strunk, so there is nothing in free-space */ + HDmemset(&state, 0, sizeof(frspace_state_t)); + if(check_stats(frsp, &state)) + TEST_ERROR + + /* section B should not be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE50), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* section A should not be there in free-space */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)(TEST_SECT_SIZE30), (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node_found) TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_sect_shrink() */ + +/* + * To verify a section's class is changed via H5FS_sect_change_class() + * + * Test 1: + * Add section A with TEST_FSPACE_SECT_TYPE class type with H5FS_CLS_GHOST_OBJ setting + * Add section B with TEST_FSPACE_SECT_TYPE_NONE class type without H5FS_CLS_GHOST_OBJ setting + * Change section A's class to the second section's class + * Result: serial_sect_count is incremented by 1; ghost_sect_count is decremented by 1 + * + * Test 2: + * Add section A with TEST_FSPACE_SECT_TYPE class type with H5FS_CLS_SEPAR_OBJ setting + * Add section B with TEST_FSPACE_SECT_TYPE_NONE class type without H5FS_CLS_SEPAR_OBJ setting + * Add section C with TEST_FSPACE_SECT_TYPE_NONE class type without H5FS_CLS_SEPAR_OBJ setting + * Sections B & C are on the merge list + * Change section class of B and C to A's section class + * Result: the merge list should be null and the class of sections B & C should be changed + */ +static int +test_fs_sect_change_class(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node1=NULL, *sect_node2=NULL, *sect_node3=NULL; + unsigned init_flags=0; + TEST_free_section_t *node; + htri_t node_found = FALSE; + + TESTING("the change of section class via H5FS_sect_change_class() in free-space: 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 + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = H5FS_CLS_GHOST_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR60, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += TEST_SECT_SIZE30; + state.tot_sect_count += 1; + state.ghost_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE_NONE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += TEST_SECT_SIZE50; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + if (H5FS_sect_change_class(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + TEST_FSPACE_SECT_TYPE_NONE) < 0) + TEST_ERROR + + state.serial_sect_count += 1; + state.ghost_sect_count -=1; + if(check_stats(frsp, &state)) + TEST_ERROR + + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE30, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node->sect_info.type != TEST_FSPACE_SECT_TYPE_NONE) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + /* + * TEST 2 + */ + TESTING("the merge of sections when H5FS_sect_add() to free-space: test 2"); + + /* Re-open the file */ + if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + init_flags = H5FS_CLS_SEPAR_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE30, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE50, TEST_FSPACE_SECT_TYPE_NONE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* + * Add section C + */ + if(NULL == (sect_node3 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node3, (haddr_t)TEST_SECT_ADDR200, (hsize_t)TEST_SECT_SIZE80, TEST_FSPACE_SECT_TYPE_NONE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + /* change the class of B to A's class */ + if (H5FS_sect_change_class(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + TEST_FSPACE_SECT_TYPE) < 0) + TEST_ERROR + + /* change the class of C to A's class */ + if (H5FS_sect_change_class(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node3, + TEST_FSPACE_SECT_TYPE) < 0) + TEST_ERROR + + /* the merge_list should be empty */ + if (frsp->sinfo->merge_list) + if (H5SL_count(frsp->sinfo->merge_list)) + TEST_ERROR + + /* verify that section B has changed class */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE50, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node->sect_info.type != TEST_FSPACE_SECT_TYPE) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* verify that section C has changed class */ + if((node_found = H5FS_sect_find(f, H5P_DATASET_XFER_DEFAULT, frsp, + (hsize_t)TEST_SECT_SIZE80, (H5FS_section_info_t **)&node)) < 0) + FAIL_STACK_ERROR + + if (node->sect_info.type != TEST_FSPACE_SECT_TYPE) + TEST_ERROR + + if(TEST_sect_free((H5FS_section_info_t *)node) < 0) + TEST_ERROR + + /* remove section A from free-space */ + if(H5FS_sect_remove(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1) < 0) + FAIL_STACK_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_sect_change_class() */ + + +/* + * To verify the extension of a block using space from a section in free-space + * + * Test 1: Try to extend the block by requested-size, which is equal to section B's size + * Add section A (addr=70, size=5) + * Add section B (addr=100, size=40) + * Try to extend the block (addr=80, size=20) by 40, which is the same as section B's size + * Result: succeed in extending the block + * + * Test 2: Try to extend the block by requested-size, which is greater than section B's size + * Add section A (addr=70, size=5) + * Add section B (addr=100, size=40) + * Try to extend the block (addr=80, size=20) by 50, which is greater than section B's size + * Result: fail in extending the block + * + * Test 3: Try to extend the block by requested-size, which is less than section B's size + * Add section A (addr=70, size=5) + * Add section B (addr=100, size=40) + * Try to extend the block (addr=80, size=20) by 30, which is less than section B's size + * Result: succeed in extending the block and a section of size=10 is left in free-space + * + * Test 4: Try to extend the block which does not adjoin section B + * Add section A (addr=70, size=5) + * Add section B (addr=100, size=40) + * Try to extend the block (addr=80, size=15) by 40 + * Result: fail in extending the block because: + * the block does not adjoin section B (80+15 != addr of section B (80)) + * even though the requested-size is equal to section B's size + * + */ +static int +test_fs_sect_extend(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + frspace_state_t state; /* State of free space*/ + + TEST_free_section_t *sect_node1=NULL, *sect_node2=NULL; + unsigned init_flags=0; + + TESTING("a block's extension by requested-size which is = adjoining free section's size: Test 1"); + + h5_fixname(FILENAME[0], fapl, filename, sizeof(filename)); + + /* Create the file to work on */ + if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + FAIL_STACK_ERROR + + /* Get a pointer to the internal file object */ + if(NULL == (f = H5I_object(file))) + FAIL_STACK_ERROR + + /* + * TEST 1 + */ + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE5, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE40, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Extend a block by requested-size */ + if(H5FS_sect_try_extend(f, H5P_DATASET_XFER_DEFAULT, frsp, (haddr_t)TEST_SECT_SIZE80, (hsize_t)TEST_SECT_SIZE20, (hsize_t)TEST_SECT_SIZE40) < 0) + TEST_ERROR + + /* Succeed in extending the block: free space info is decremented accordingly */ + state.tot_space -= sect_node2->sect_info.size; + state.tot_sect_count -= 1; + state.serial_sect_count -= 1; + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + PASSED() + + /* + * TEST 2 + */ + TESTING("a block's extension by requested-size which is > adjoining free section's size: Test 2"); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE5, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE40, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Extend the block by requested-size */ + if(H5FS_sect_try_extend(f, H5P_DATASET_XFER_DEFAULT, frsp, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE20, (hsize_t)TEST_SECT_SIZE50) < 0) + TEST_ERROR + + /* Not able to extend the block: free space info remains the same */ + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + PASSED() + + /* + * Test 3 + */ + TESTING("a block's extension by requested-size which is < adjoining free section's size: Test 3"); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE5, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE40, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Extend the block by requested-size */ + if(H5FS_sect_try_extend(f, H5P_DATASET_XFER_DEFAULT, frsp, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE20, (hsize_t)TEST_SECT_SIZE30) < 0) + TEST_ERROR + + /* Succeed in extending the block: total free space is decreased but other info remains the same */ + state.tot_space -= 30; + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + PASSED() + + /* + * TEST 4 + */ + TESTING("a block's extension by requested-size which does not adjoin any free section: Test 4"); + + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + /* + * Add section A + */ + if(NULL == (sect_node1 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node1, (haddr_t)TEST_SECT_ADDR70, (hsize_t)TEST_SECT_SIZE5, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node1, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + HDmemset(&state, 0, sizeof(frspace_state_t)); + state.tot_space += sect_node1->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* + * Add section B + */ + if(NULL == (sect_node2 = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + init_sect_node(sect_node2, (haddr_t)TEST_SECT_ADDR100, (hsize_t)TEST_SECT_SIZE40, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node2, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + + state.tot_space += sect_node2->sect_info.size; + state.tot_sect_count += 1; + state.serial_sect_count += 1; + + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Extend the block by requested-size */ + if(H5FS_sect_try_extend(f, H5P_DATASET_XFER_DEFAULT, frsp, (haddr_t)TEST_SECT_ADDR80, (hsize_t)TEST_SECT_SIZE15, (hsize_t)TEST_SECT_SIZE40) < 0) + TEST_ERROR + + /* Not able to extend the block: free space manager info remains the same */ + if(check_stats(frsp, &state)) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + PASSED() + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_sect_extend() */ + + +/* + * To verify the iteration of free-space sections + * + * Create free-space manager with H5FS_CLS_SEPAR_OBJ + * Create a whole bunch of sections + * Iterate through all sections and collect size and count for all sections + * Check info with H5FS_sect_stat() + */ +static int +test_fs_sect_iterate(hid_t fapl) +{ + hid_t file = -1; /* File ID */ + char filename[FILENAME_LEN]; /* Filename to use */ + H5F_t *f = NULL; /* Internal file object pointer */ + H5FS_t *frsp = NULL; /* pointer to free space structure */ + haddr_t fs_addr=HADDR_UNDEF; /* address of free space */ + size_t nclasses; + H5FS_create_t cparam; /* creation parameters */ + + TEST_free_section_t *sect_node=NULL; + unsigned init_flags=0, sect_size; + TEST_iter_ud_t udata; + int i; + hsize_t tot_space, nsects; + + TESTING("iteration of sections in the 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 = H5I_object(file))) + FAIL_STACK_ERROR + + init_cparam(&cparam); + nclasses = NELMTS(test_classes); + udata.tot_size = 0; + udata.tot_sect_count = 0; + + init_flags = H5FS_CLS_SEPAR_OBJ; + if(NULL == (frsp = H5FS_create(f, H5P_DATASET_XFER_DEFAULT, &fs_addr, + &cparam, nclasses, test_classes, &init_flags, (hsize_t)FSPACE_THRHD_DEF, (hsize_t)FSPACE_ALIGN_DEF))) + FAIL_STACK_ERROR + + if(!H5F_addr_defined(fs_addr)) + TEST_ERROR + + for (i = 1; i <= NUM_SECTIONS; i++) { + if(NULL == (sect_node = H5FL_MALLOC(TEST_free_section_t))) + FAIL_STACK_ERROR + + sect_size = ((i-1) % 9) + 1; + init_sect_node(sect_node, (haddr_t)i*10, (hsize_t)sect_size, TEST_FSPACE_SECT_TYPE, H5FS_SECT_LIVE); + + if(H5FS_sect_add(f, H5P_DATASET_XFER_DEFAULT, frsp, (H5FS_section_info_t *)sect_node, + H5FS_ADD_RETURNED_SPACE, NULL)) + FAIL_STACK_ERROR + } + + if(H5FS_sect_iterate(f, H5P_DATASET_XFER_DEFAULT, frsp, TEST_sects_cb, &udata) < 0) + TEST_ERROR + + H5FS_sect_stats(frsp, &tot_space, &nsects); + + if (udata.tot_size != tot_space) + TEST_ERROR + if (udata.tot_sect_count != nsects) + TEST_ERROR + + /* Close the free space manager */ + if(H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp) < 0) + FAIL_STACK_ERROR + frsp = NULL; + + /* Delete free space manager */ + if(H5FS_delete(f, H5P_DATASET_XFER_DEFAULT, fs_addr) < 0) + FAIL_STACK_ERROR + fs_addr = HADDR_UNDEF; + + /* Close the file */ + if(H5Fclose(file) < 0) + FAIL_STACK_ERROR + + PASSED() + + return(0); + +error: + H5E_BEGIN_TRY { + if(frsp) + H5FS_close(f, H5P_DATASET_XFER_DEFAULT, frsp); + H5Fclose(file); + } H5E_END_TRY; + return(1); +} /* test_fs_sect_iterate() */ + + +int +main(void) +{ + + hid_t fapl = -1; /* File access property list for data files */ + unsigned nerrors = 0; /* Cumulative error count */ + + fapl = h5_fileaccess(); + + /* make sure alignment is not set for tests to succeed */ + if(H5Pset_alignment(fapl, (hsize_t)1, (hsize_t)1) < 0) + TEST_ERROR + + nerrors += test_fs_create(fapl); + nerrors += test_fs_sect_add(fapl); + nerrors += test_fs_sect_merge(fapl); + nerrors += test_fs_sect_shrink(fapl); + nerrors += test_fs_sect_find(fapl); + nerrors += test_fs_sect_change_class(fapl); + nerrors += test_fs_sect_extend(fapl); + nerrors += test_fs_sect_iterate(fapl); + + if(nerrors) + goto error; + puts("All free-space tests passed."); + +#ifdef OUT + h5_cleanup(FILENAME, fapl); +#endif + return (0); + +error: + puts("*** TESTS FAILED ***"); + H5E_BEGIN_TRY { + H5Pclose(fapl); + } H5E_END_TRY; + return (1); +} /* main() */ |