summaryrefslogtreecommitdiffstats
path: root/test/freespace.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2008-10-07 04:17:35 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2008-10-07 04:17:35 (GMT)
commit9f60f016ab71cf8ce39c859fd9eb61c6fca35d63 (patch)
tree0ddbcb2f8707b578af22c62748420b9e3c19177b /test/freespace.c
parent504c67846e6a4cc5706403bf21a9ae4f07aae7b4 (diff)
downloadhdf5-9f60f016ab71cf8ce39c859fd9eb61c6fca35d63.zip
hdf5-9f60f016ab71cf8ce39c859fd9eb61c6fca35d63.tar.gz
hdf5-9f60f016ab71cf8ce39c859fd9eb61c6fca35d63.tar.bz2
[svn-r15800] Description:
Bring file free space branch changes through r15795 into trunk, which includes a fair bit of code cleanup & rearrangement along with a couple of bug fixes also. Tested on: Mac OS X/32 10.5.5 (amazon) in debug mode Mac OS X/32 10.5.5 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) w/Intel compilers w/default API=1.6.x, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode
Diffstat (limited to 'test/freespace.c')
-rw-r--r--test/freespace.c2805
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() */