From ac4c35cca592fc598c5a064fd8f769bbef69bd75 Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Wed, 10 Jun 1998 09:43:15 -0500 Subject: [svn-r418] ./html/Files.html ./src/H5F.c ./src/HFcore.c ./src/H5Ffamily.c ./src/H5Flow.c ./src/H5Fmpio.c ./src/H5Fprivate.h ./src/H5Fsec2.c ./src/H5Fsplit.c ./src/H5Fstdio.c ./src/H5MF.c ./src/H5P.c ./src/H5Ppublic.h Added H5Pset_alignment() so that it is now possible to align file allocation requests on application-specified boundaries. Any request >= the specified threshold will begin on an address which is a multiple of the specified alignment. Defaults are one for threshold and alignment. The alignment is done on relative addresses, so the size of the user block can affect the location of the data in the file. ./src/H5D.c ./src/dsets.c Added a test for, and fixed the data space caching bug in datasets. Extending a dataset through one handle will cause all other handles to the same dataset to get the new dataset size. ./src/H5S.c ./src/H5Sprivate.h Removed an unused argument from H5S_read() which duplicated information from the other argument. ./config/linux Made `--enable-parallel' the default on my system. It used to be that way before but then I accidently turned it off and forgot about it. ./src/H5Fmpio.c Qualified some function arguments with __unused__. Changed a couple places where NULL was returned on error for herr_t functions. ./src/H5P.c Removed unused autos from H5Pset_mpi(). --- src/H5D.c | 97 ++++++++++++++++++++++------------ src/H5F.c | 2 + src/H5Fcore.c | 19 +++---- src/H5Ffamily.c | 15 +++--- src/H5Flow.c | 66 +++++++++++++++++++++++ src/H5Fmpio.c | 29 ++++++----- src/H5Fprivate.h | 21 +++++++- src/H5Fsec2.c | 5 +- src/H5Fsplit.c | 90 ++++++++++++++++++++++++++++---- src/H5Fstdio.c | 5 +- src/H5MF.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++-------- src/H5P.c | 98 ++++++++++++++++++++++++++++++++++- src/H5Ppublic.h | 3 ++ src/H5S.c | 7 +-- src/H5Sprivate.h | 2 +- test/.distdep | 23 +++++---- test/dsets.c | 74 ++++++++++++++++++++++++++ 17 files changed, 595 insertions(+), 116 deletions(-) diff --git a/src/H5D.c b/src/H5D.c index 92fbccd..10231fc 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -43,7 +43,6 @@ static char RcsId[] = "@(#)$Revision$"; struct H5D_t { H5G_entry_t ent; /*cached object header stuff */ H5T_t *type; /*datatype of this dataset */ - H5S_t *space; /*dataspace of this dataset */ H5D_create_t *create_parms; /*creation parameters */ H5O_layout_t layout; /*data layout */ }; @@ -343,14 +342,16 @@ H5Dclose(hid_t dataset_id) * Wednesday, January 28, 1998 * * Modifications: - * + * Robb Matzke, 9 Jun 1998 + * The data space is not constant and is no longer cached by the dataset + * struct. *------------------------------------------------------------------------- */ hid_t H5Dget_space (hid_t dataset_id) { H5D_t *dataset = NULL; - H5S_t *copied_space = NULL; + H5S_t *space = NULL; hid_t ret_value = FAIL; FUNC_ENTER (H5Dget_space, FAIL); @@ -361,14 +362,15 @@ H5Dget_space (hid_t dataset_id) HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); } - /* Copy the data space */ - if (NULL==(copied_space=H5S_copy (dataset->space))) { + /* Read the data space message and return a data space object */ + if (NULL==(space=H5S_read (&(dataset->ent)))) { HRETURN_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to copy the data space"); + "unable to load space info from dataset header"); } /* Create an atom */ - if ((ret_value=H5I_register (H5_DATASPACE, copied_space))<0) { + if ((ret_value=H5I_register (H5_DATASPACE, space))<0) { + H5S_close (space); HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space"); } @@ -738,6 +740,8 @@ H5Dextend (hid_t dataset_id, const hsize_t *size) * Thursday, December 4, 1997 * * Modifications: + * Robb Matzke, 9 Jun 1998 + * The data space message is no longer cached in the dataset struct. * *------------------------------------------------------------------------- */ @@ -771,7 +775,6 @@ H5D_create(H5G_t *loc, const char *name, const H5T_t *type, const H5S_t *space, new_dset = H5MM_xcalloc(1, sizeof(H5D_t)); H5F_addr_undef(&(new_dset->ent.header)); new_dset->type = H5T_copy(type, H5T_COPY_ALL); - new_dset->space = H5S_copy(space); new_dset->create_parms = H5P_copy (H5P_DATASET_CREATE, create_parms); efl = &(new_dset->create_parms->efl); @@ -852,7 +855,7 @@ H5D_create(H5G_t *loc, const char *name, const H5T_t *type, const H5S_t *space, /* Update the type and space header messages */ if (H5O_modify(&(new_dset->ent), H5O_DTYPE, 0, H5O_FLAG_CONSTANT|H5O_FLAG_SHARED, new_dset->type)<0 || - H5S_modify(&(new_dset->ent), new_dset->space) < 0) { + H5S_modify(&(new_dset->ent), space) < 0) { HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to update type or space header messages"); } @@ -915,7 +918,6 @@ H5D_create(H5G_t *loc, const char *name, const H5T_t *type, const H5S_t *space, done: if (!ret_value && new_dset) { if (new_dset->type) H5T_close(new_dset->type); - if (new_dset->space) H5S_close(new_dset->space); if (new_dset->create_parms) { H5P_close (H5P_DATASET_CREATE, new_dset->create_parms); new_dset->create_parms = NULL; @@ -945,6 +947,8 @@ H5D_create(H5G_t *loc, const char *name, const H5T_t *type, const H5S_t *space, * Thursday, December 4, 1997 * * Modifications: + * Robb Matzke, 9 Jun 1998 + * The data space message is no longer cached in the dataset struct. * *------------------------------------------------------------------------- */ @@ -976,10 +980,9 @@ H5D_open(H5G_t *loc, const char *name) } /* Get the type and space */ - if (NULL==(dataset->type=H5O_read(&(dataset->ent), H5O_DTYPE, 0, NULL)) || - NULL==(dataset->space=H5S_read(f, &(dataset->ent)))) { + if (NULL==(dataset->type=H5O_read(&(dataset->ent), H5O_DTYPE, 0, NULL))) { HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, - "unable to load type or space info from dataset header"); + "unable to load type info from dataset header"); } /* Get the optional compression message */ @@ -1041,9 +1044,6 @@ H5D_open(H5G_t *loc, const char *name) if (dataset->type) { H5T_close(dataset->type); } - if (dataset->space) { - H5S_close(dataset->space); - } if (dataset->create_parms) { H5P_close (H5P_DATASET_CREATE, dataset->create_parms); } @@ -1072,6 +1072,8 @@ H5D_open(H5G_t *loc, const char *name) * Thursday, December 4, 1997 * * Modifications: + * Robb Matzke, 9 Jun 1998 + * The data space message is no longer cached in the dataset struct. * *------------------------------------------------------------------------- */ @@ -1086,11 +1088,10 @@ H5D_close(H5D_t *dataset) assert(dataset && dataset->ent.file); /* - * Release dataset type and space - there isn't much we can do if one of - * these fails, so we just continue. + * Release data type and creation property list -- there isn't much we + * can do if one of these fails, so we just continue. */ free_failed = (H5T_close(dataset->type) < 0 || - H5S_close(dataset->space) < 0 || H5P_close (H5P_DATASET_CREATE, dataset->create_parms)); /* Close the dataset object */ @@ -1107,8 +1108,8 @@ H5D_close(H5D_t *dataset) if (free_failed) { HRETURN_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "couldn't free the type or space, but the dataset was " - "freed anyway."); + "couldn't free the type or creation property list, " + "but the dataset was freed anyway."); } FUNC_LEAVE(SUCCEED); } @@ -1127,6 +1128,8 @@ H5D_close(H5D_t *dataset) * Thursday, December 4, 1997 * * Modifications: + * Robb Matzke, 9 Jun 1998 + * The data space is no longer cached in the dataset struct. * *------------------------------------------------------------------------- */ @@ -1152,6 +1155,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, size_t target_size; /*desired buffer size */ size_t request_nelmts; /*requested strip mine */ H5T_bkg_t need_bkg; /*type of background buf*/ + H5S_t *free_this_space=NULL; /*data space to free */ #ifdef H5T_DEBUG H5_timer_t timer; #endif @@ -1163,7 +1167,13 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, assert(mem_type); assert(xfer_parms); assert(buf); - if (!file_space) file_space = dataset->space; + if (!file_space) { + if (NULL==(free_this_space=H5S_read (&(dataset->ent)))) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to read data space from dataset header"); + } + file_space = free_this_space; + } if (!mem_space) mem_space = file_space; nelmts = H5S_get_npoints(mem_space); @@ -1387,6 +1397,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, if (bkg_buf && NULL==xfer_parms->bkg_buf) { H5MM_xfree (bkg_buf); } + if (free_this_space) H5S_close (free_this_space); FUNC_LEAVE(ret_value); } @@ -1405,6 +1416,8 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, * Thursday, December 4, 1997 * * Modifications: + * Robb Matzke, 9 Jun 1998 + * The data space is no longer cached in the dataset struct. * *------------------------------------------------------------------------- */ @@ -1429,6 +1442,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, size_t target_size; /*desired buffer size */ size_t request_nelmts; /*requested strip mine */ H5T_bkg_t need_bkg; /*type of background buf*/ + H5S_t *free_this_space=NULL; /*data space to free */ #ifdef H5T_DEBUG H5_timer_t timer; #endif @@ -1440,7 +1454,13 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, assert(mem_type); assert(xfer_parms); assert(buf); - if (!file_space) file_space = dataset->space; + if (!file_space) { + if (NULL==(free_this_space=H5S_read (&(dataset->ent)))) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to read data space from dataset header"); + } + file_space = free_this_space; + } if (!mem_space) mem_space = file_space; nelmts = H5S_get_npoints(mem_space); @@ -1666,6 +1686,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, if (bkg_buf && NULL==xfer_parms->bkg_buf) { H5MM_xfree (bkg_buf); } + if (free_this_space) H5S_close (free_this_space); FUNC_LEAVE(ret_value); } @@ -1689,7 +1710,8 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, herr_t H5D_extend (H5D_t *dataset, const hsize_t *size) { - herr_t changed; + herr_t changed, ret_value=FAIL; + H5S_t *space = NULL; FUNC_ENTER (H5D_extend, FAIL); @@ -1698,26 +1720,33 @@ H5D_extend (H5D_t *dataset, const hsize_t *size) assert (size); /* - * Restrictions on extensions were checked when the dataset was created. - * All extensions are allowed here since none should be able to muck - * things up. + * NOTE: Restrictions on extensions were checked when the dataset was + * created. All extensions are allowed here since none should be + * able to muck things up. */ - /*void*/ + /* Increase the size of the data space */ - if ((changed=H5S_extend (dataset->space, size))<0) { - HRETURN_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to increase size of data space"); + if (NULL==(space=H5S_read (&(dataset->ent)))) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to read data space info from dataset header"); + } + if ((changed=H5S_extend (space, size))<0) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to increase size of data space"); } /* Save the new dataspace in the file if necessary */ if (changed>0 && - H5S_modify (&(dataset->ent), dataset->space)<0) { - HRETURN_ERROR (H5E_DATASET, H5E_WRITEERROR, FAIL, + H5S_modify (&(dataset->ent), space)<0) { + HGOTO_ERROR (H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace"); } + ret_value = SUCCEED; - FUNC_LEAVE (SUCCEED); + done: + H5S_close (space); + FUNC_LEAVE (ret_value); } diff --git a/src/H5F.c b/src/H5F.c index c782e53..ad26fc9 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -145,6 +145,8 @@ H5F_init_interface(void) H5F_access_dflt.mdc_nelmts = H5AC_NSLOTS; H5F_access_dflt.rdcc_nbytes = 1024*1024; /*1MB*/ H5F_access_dflt.rdcc_w0 = 0.75; /*preempt fully read chunks*/ + H5F_access_dflt.threshold = 1; /*alignment applies to everything*/ + H5F_access_dflt.alignment = 1; /*no alignment*/ H5F_access_dflt.driver = H5F_LOW_DFLT; #if (H5F_LOW_DFLT == H5F_LOW_SEC2) /* Nothing to initialize */ diff --git a/src/H5Fcore.c b/src/H5Fcore.c index 99f64fb..c0bfbf7 100644 --- a/src/H5Fcore.c +++ b/src/H5Fcore.c @@ -41,13 +41,14 @@ static herr_t H5F_core_write(H5F_low_t *lf, const H5F_access_t *access_parms, const uint8 *buf); const H5F_low_class_t H5F_LOW_CORE_g[1] = {{ - H5F_core_access, /* access method */ - H5F_core_open, /* open method */ - H5F_core_close, /* close method */ - H5F_core_read, /* read method */ - H5F_core_write, /* write method */ - NULL, /* flush method */ - NULL, /* extend method */ + H5F_core_access, /*access method */ + H5F_core_open, /*open method */ + H5F_core_close, /*close method */ + H5F_core_read, /*read method */ + H5F_core_write, /*write method */ + NULL, /*flush method */ + NULL, /*extend method */ + NULL, /*alloc method */ }}; @@ -186,7 +187,7 @@ H5F_core_close(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms) */ static herr_t H5F_core_read(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms, - const H5D_transfer_t xfer_mode, + const H5D_transfer_t __unused__ xfer_mode, const haddr_t *addr, size_t size, uint8 *buf) { size_t n; @@ -236,7 +237,7 @@ H5F_core_read(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms, */ static herr_t H5F_core_write(H5F_low_t *lf, const H5F_access_t *access_parms, - const H5D_transfer_t xfer_mode, + const H5D_transfer_t __unused__ xfer_mode, const haddr_t *addr, size_t size, const uint8 *buf) { size_t need_more; diff --git a/src/H5Ffamily.c b/src/H5Ffamily.c index e887acc..01b5682 100644 --- a/src/H5Ffamily.c +++ b/src/H5Ffamily.c @@ -52,13 +52,14 @@ static herr_t H5F_fam_write(H5F_low_t *lf, const H5F_access_t *access_parms, static herr_t H5F_fam_flush(H5F_low_t *lf, const H5F_access_t *access_parms); const H5F_low_class_t H5F_LOW_FAMILY_g[1] = {{ - H5F_fam_access, /* access method */ - H5F_fam_open, /* open method */ - H5F_fam_close, /* close method */ - H5F_fam_read, /* read method */ - H5F_fam_write, /* write method */ - H5F_fam_flush, /* flush method */ - NULL, /* extend method */ + H5F_fam_access, /*access method */ + H5F_fam_open, /*open method */ + H5F_fam_close, /*close method */ + H5F_fam_read, /*read method */ + H5F_fam_write, /*write method */ + H5F_fam_flush, /*flush method */ + NULL, /*extend method */ + NULL, /*alloc method */ }}; diff --git a/src/H5Flow.c b/src/H5Flow.c index 82e1f1a..91fb495 100644 --- a/src/H5Flow.c +++ b/src/H5Flow.c @@ -515,6 +515,72 @@ H5F_low_extend(H5F_low_t *lf, const H5F_access_t *access_parms, intn op, FUNC_LEAVE(SUCCEED); } + + +/*------------------------------------------------------------------------- + * Function: H5F_low_alloc + * + * Purpose: Determines if a free block BLK can satisfy a request for SIZE + * bytes of memory from file F. If SIZE >= THRESH then the + * memory must be aligned on an ALIGN-byte boundary. Alignment + * is wrt the relative file addresses (that is, the size of the + * user-defined block at the beginning of the file is subtracted + * from the addresses before aligning them). + * + * Return: Success: Positive if the free block exactly satisfies + * the request; zero if the free block + * over-satisfies the request. In either case, + * ADDR will be the address within the free + * block where the request can be satisfied. + * + * Failure: FAIL with the output value of ADDR + * undefined. + * + * Programmer: Robb Matzke + * Tuesday, June 9, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +intn +H5F_low_alloc (H5F_low_t *lf, intn op, hsize_t alignment, hsize_t threshold, + size_t size, H5MF_free_t *blk, haddr_t *addr/*out*/) +{ + intn ret_value = FAIL; + hsize_t wasted; + + FUNC_ENTER (H5MF_acceptable, FAIL); + assert (lf); + assert (alignment>0); + assert (size>0); + assert (blk); + assert (addr); + + if (lf->type->alloc) { + ret_value = (lf->type->alloc)(lf, op, alignment, threshold, size, blk, + addr/*out*/); + } else { + if (size>=threshold) { + wasted = blk->addr.offset % alignment; + } else { + wasted = 0; + } + if (0==wasted && size==blk->size) { + /* exact match */ + *addr = blk->addr; + ret_value = 1; + } else if (blk->size>wasted && blk->size-wasted>=size) { + /* over-satisfied */ + *addr = blk->addr; + H5F_addr_inc (addr, wasted); + ret_value = 0; + } + } + + FUNC_LEAVE (ret_value); +} + /*------------------------------------------------------------------------- * Function: H5F_low_seteof diff --git a/src/H5Fmpio.c b/src/H5Fmpio.c index 74a75f4..ceca1b3 100644 --- a/src/H5Fmpio.c +++ b/src/H5Fmpio.c @@ -89,14 +89,15 @@ static herr_t H5F_mpio_flush(H5F_low_t *lf, const H5F_access_t *access_parms); static herr_t H5F_MPIOff_to_haddr(MPI_Offset mpi_off, haddr_t *addr); static herr_t H5F_haddr_to_MPIOff(haddr_t addr, MPI_Offset *mpi_off); -const H5F_low_class_t H5F_LOW_MPIO_g[1] = {{ - H5F_mpio_access, /* access method */ - H5F_mpio_open, /* open method */ - H5F_mpio_close, /* close method */ - H5F_mpio_read, /* read method */ - H5F_mpio_write, /* write method */ - H5F_mpio_flush, /* flush method */ - NULL /* extend method */ +const H5F_low_class_t H5F_LOW_MPIO_g[1] = {{ + H5F_mpio_access, /*access method */ + H5F_mpio_open, /*open method */ + H5F_mpio_close, /*close method */ + H5F_mpio_read, /*read method */ + H5F_mpio_write, /*write method */ + H5F_mpio_flush, /*flush method */ + NULL, /*extend method */ + NULL, /*alloc method */ }}; ino_t mpio_inode_num = 0; /* fake "inode" number */ @@ -347,7 +348,7 @@ H5F_mpio_open(const char *name, const H5F_access_t *access_parms, uintn flags, *------------------------------------------------------------------------- */ static herr_t -H5F_mpio_close(H5F_low_t *lf, const H5F_access_t *access_parms) +H5F_mpio_close(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms) { int mpierr; char mpierrmsg[MPI_MAX_ERROR_STRING]; @@ -404,7 +405,7 @@ H5F_mpio_close(H5F_low_t *lf, const H5F_access_t *access_parms) *------------------------------------------------------------------------- */ static herr_t -H5F_mpio_read(H5F_low_t *lf, const H5F_access_t *access_parms, +H5F_mpio_read(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms, const H5D_transfer_t xfer_mode, const haddr_t *addr, size_t size, uint8 *buf/*out*/) { @@ -448,7 +449,7 @@ H5F_mpio_read(H5F_low_t *lf, const H5F_access_t *access_parms, break; default: - HRETURN_ERROR(H5E_IO, H5E_BADVALUE, NULL, "invalid file access mode"); + HRETURN_ERROR(H5E_IO, H5E_BADVALUE, FAIL, "invalid file access mode"); } if (mpierr != MPI_SUCCESS) { MPI_Error_string( mpierr, mpierrmsg, &msglen ); @@ -528,7 +529,7 @@ H5F_mpio_read(H5F_low_t *lf, const H5F_access_t *access_parms, *------------------------------------------------------------------------- */ static herr_t -H5F_mpio_write(H5F_low_t *lf, const H5F_access_t *access_parms, +H5F_mpio_write(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms, const H5D_transfer_t xfer_mode, const haddr_t *addr, size_t size, const uint8 *buf) { @@ -570,7 +571,7 @@ H5F_mpio_write(H5F_low_t *lf, const H5F_access_t *access_parms, break; default: - HRETURN_ERROR(H5E_IO, H5E_BADVALUE, NULL, "invalid file access mode"); + HRETURN_ERROR(H5E_IO, H5E_BADVALUE, FAIL, "invalid file access mode"); } if (mpierr != MPI_SUCCESS) { MPI_Error_string( mpierr, mpierrmsg, &msglen ); @@ -606,7 +607,7 @@ H5F_mpio_write(H5F_low_t *lf, const H5F_access_t *access_parms, *------------------------------------------------------------------------- */ static herr_t -H5F_mpio_flush(H5F_low_t *lf, const H5F_access_t *access_parms) +H5F_mpio_flush(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms) { int mpierr; char mpierrmsg[MPI_MAX_ERROR_STRING]; diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 5b0ec5b..dcf5e69 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -242,6 +242,8 @@ typedef struct H5F_access_t { intn mdc_nelmts; /* Size of meta data cache (nelmts) */ size_t rdcc_nbytes; /* Size of raw data chunk cache (bytes) */ double rdcc_w0; /* Preempt read chunks first? [0.0..1.0]*/ + hsize_t threshold; /* Threshold for alignment */ + hsize_t alignment; /* Alignment */ H5F_driver_t driver; /* Low level file driver */ union { @@ -291,6 +293,13 @@ typedef enum { H5F_OP_READ /* Last operation was a read */ } H5F_fileop_t; +/* A free-list entry */ +#define H5MF_NFREE 32 /*size of free block array */ +typedef struct H5MF_free_t { + haddr_t addr; /*file address */ + hsize_t size; /*size of free area */ +} H5MF_free_t; + /* * Define the low-level file interface. */ @@ -312,7 +321,10 @@ typedef struct H5F_low_class_t { const H5F_access_t *access_parms); herr_t (*extend)(struct H5F_low_t *lf, const H5F_access_t *access_parms, - intn op, hsize_t size, haddr_t *addr); + intn op, hsize_t size, haddr_t *addr/*out*/); + intn (*alloc)(struct H5F_low_t *lf, intn op, hsize_t alignment, + hsize_t threshold, size_t size, H5MF_free_t *blk, + haddr_t *addr/*out*/); } H5F_low_class_t; typedef struct H5F_low_t { @@ -423,6 +435,8 @@ typedef struct H5F_file_t { intn ncwfs; /* Num entries on cwfs list */ struct H5HG_heap_t **cwfs; /* Global heap cache */ H5F_rdcc_t rdcc; /* Raw data chunk cache */ + intn fl_nfree; /*number of free blocks in array */ + H5MF_free_t fl_free[H5MF_NFREE]; /*free block array */ } H5F_file_t; /* @@ -536,8 +550,11 @@ herr_t H5F_block_write(H5F_t *f, const haddr_t *addr, hsize_t size, /* Functions that operate directly on low-level files */ const H5F_low_class_t *H5F_low_class (H5F_driver_t driver); herr_t H5F_low_extend(H5F_low_t *lf, const H5F_access_t *access_parms, - intn op, hsize_t size, haddr_t *addr); + intn op, hsize_t size, haddr_t *addr/*out*/); herr_t H5F_low_seteof(H5F_low_t *lf, const haddr_t *addr); +intn H5F_low_alloc (H5F_low_t *lf, intn op, hsize_t alignment, + hsize_t threshold, size_t size, H5MF_free_t *blk, + haddr_t *addr/*out*/); hbool_t H5F_low_access(const H5F_low_class_t *type, const char *name, const H5F_access_t *access_parms, int mode, H5F_search_t *key); diff --git a/src/H5Fsec2.c b/src/H5Fsec2.c index b0be347..d61d3a0 100644 --- a/src/H5Fsec2.c +++ b/src/H5Fsec2.c @@ -47,6 +47,7 @@ const H5F_low_class_t H5F_LOW_SEC2_g[1] = {{ H5F_sec2_write, /* write method */ NULL, /* flush method */ NULL, /* extend method */ + NULL, /* alloc method */ }}; @@ -161,7 +162,7 @@ H5F_sec2_close(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms) */ static herr_t H5F_sec2_read(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms, - const H5D_transfer_t xfer_mode, + const H5D_transfer_t __unused__ xfer_mode, const haddr_t *addr, size_t size, uint8 *buf) { ssize_t n; @@ -268,7 +269,7 @@ H5F_sec2_read(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms, */ static herr_t H5F_sec2_write(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms, - const H5D_transfer_t xfer_mode, + const H5D_transfer_t __unused__ xfer_mode, const haddr_t *addr, size_t size, const uint8 *buf) { uint64 mask; diff --git a/src/H5Fsplit.c b/src/H5Fsplit.c index bc57db3..b875023 100644 --- a/src/H5Fsplit.c +++ b/src/H5Fsplit.c @@ -43,15 +43,19 @@ static herr_t H5F_split_write(H5F_low_t *lf, const H5F_access_t *access_parms, static herr_t H5F_split_flush(H5F_low_t *lf, const H5F_access_t *access_parms); static herr_t H5F_split_extend(H5F_low_t *lf, const H5F_access_t *access_parms, intn op, hsize_t size, haddr_t *addr/*out*/); - -const H5F_low_class_t H5F_LOW_SPLIT_g[1] = {{ - H5F_split_access, /* access method */ - H5F_split_open, /* open method */ - H5F_split_close, /* close method */ - H5F_split_read, /* read method */ - H5F_split_write, /* write method */ - H5F_split_flush, /* flush method */ - H5F_split_extend, /* extend method */ +static intn H5F_split_alloc (H5F_low_t *lf, intn op, hsize_t alignment, + hsize_t threshold, size_t size, H5MF_free_t *blk, + haddr_t *addr/*out*/); + +const H5F_low_class_t H5F_LOW_SPLIT_g[1] = {{ + H5F_split_access, /*access method */ + H5F_split_open, /*open method */ + H5F_split_close, /*close method */ + H5F_split_read, /*read method */ + H5F_split_write, /*write method */ + H5F_split_flush, /*flush method */ + H5F_split_extend, /*extend method */ + H5F_split_alloc, /*alloc method */ }}; /* @@ -451,3 +455,71 @@ H5F_split_extend(H5F_low_t *lf, const H5F_access_t *access_parms, intn op, FUNC_LEAVE(SUCCEED); } + + +/*------------------------------------------------------------------------- + * Function: H5F_split_alloc + * + * Purpose: Determines if free block BLK in file LF can be used to + * satisfy the request for SIZE bytes. This function is + * actually the same as H5F_low_alloc() except it returns + * failure if the OP is not compatible with the block address, + * insuring that meta data is allocated from one half of the + * address space and raw data from the other half. + * + * Return: Success: Positive if the free block satisfies the + * request exactly, zero if the free block + * over-satisfies the request. The ADDR will + * contain the address within the free block + * where the request starts. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, June 9, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static intn +H5F_split_alloc (H5F_low_t *lf, intn op, hsize_t alignment, hsize_t threshold, + size_t size, H5MF_free_t *blk, haddr_t *addr/*out*/) +{ + intn ret_value = FAIL; + hsize_t wasted; + + FUNC_ENTER (H5F_split_alloc, FAIL); + assert (lf); + assert (alignment>0); + assert (size>0); + assert (blk); + assert (addr); + + switch (op) { + case H5MF_META: + if (blk->addr.offset & lf->u.split.mask) return FAIL; + break; + case H5MF_RAW: + if (0==(blk->addr.offset & lf->u.split.mask)) return FAIL; + break; + } + + if (size>=threshold) { + wasted = blk->addr.offset % alignment; + } else { + wasted = 0; + } + if (0==wasted && size==blk->size) { + /* exact match */ + *addr = blk->addr; + ret_value = 1; + } else if (blk->size>wasted && blk->size-wasted>=size) { + /* over-satisfied */ + *addr = blk->addr; + H5F_addr_inc (addr, wasted); + ret_value = 0; + } + + FUNC_LEAVE (ret_value); +} diff --git a/src/H5Fstdio.c b/src/H5Fstdio.c index 3ba7653..a472d30 100644 --- a/src/H5Fstdio.c +++ b/src/H5Fstdio.c @@ -42,6 +42,7 @@ const H5F_low_class_t H5F_LOW_STDIO_g[1] = {{ H5F_stdio_write, /* write method */ H5F_stdio_flush, /* flush method */ NULL, /* extend method */ + NULL, /* alloc method */ }}; @@ -186,7 +187,7 @@ H5F_stdio_close(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms) */ static herr_t H5F_stdio_read(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms, - const H5D_transfer_t xfer_mode, + const H5D_transfer_t __unused__ xfer_mode, const haddr_t *addr, size_t size, uint8 *buf/*out*/) { size_t n; @@ -297,7 +298,7 @@ H5F_stdio_read(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms, */ static herr_t H5F_stdio_write(H5F_low_t *lf, const H5F_access_t __unused__ *access_parms, - const H5D_transfer_t xfer_mode, + const H5D_transfer_t __unused__ xfer_mode, const haddr_t *addr, size_t size, const uint8 *buf) { uint64 mask; diff --git a/src/H5MF.c b/src/H5MF.c index a87dc39..6a51ff7 100644 --- a/src/H5MF.c +++ b/src/H5MF.c @@ -11,10 +11,13 @@ * Purpose: File memory management functions. * * Modifications: - * * Robb Matzke, 5 Aug 1997 * Added calls to H5E. * + * Robb Matzke, 8 Jun 1998 + * Implemented a very simple free list which is not persistent and which + * is lossy. + * *------------------------------------------------------------------------- */ #include @@ -27,6 +30,7 @@ /* Is the interface initialized? */ static intn interface_initialize_g = FALSE; #define INTERFACE_INIT NULL + /*------------------------------------------------------------------------- * Function: H5MF_alloc @@ -53,7 +57,12 @@ static intn interface_initialize_g = FALSE; herr_t H5MF_alloc(H5F_t *f, intn op, hsize_t size, haddr_t *addr/*out*/) { - haddr_t tmp_addr; + haddr_t tmp_addr; + intn i, found, status; + hsize_t n; + H5MF_free_t blk; + hsize_t thresh = f->shared->access_parms->threshold; + hsize_t align = f->shared->access_parms->alignment; FUNC_ENTER(H5MF_alloc, FAIL); @@ -63,30 +72,114 @@ H5MF_alloc(H5F_t *f, intn op, hsize_t size, haddr_t *addr/*out*/) assert(size > 0); assert(addr); +#if 0 + HDfprintf (stderr, "A %Hu\n", size); +#endif + + /* Fail if we don't have write access */ if (0==(f->intent & H5F_ACC_RDWR)) { HRETURN_ERROR (H5E_RESOURCE, H5E_CANTINIT, FAIL, "file is read-only"); } /* - * Eventually we'll maintain a free list(s) and try to satisfy requests - * from there. But for now we just allocate more memory from the end of - * the file. + * Try to satisfy the request from the free list. We prefer exact matches + * to partial matches, so if we find an exact match then we break out of + * the loop immediately, otherwise we keep looking for an exact match. */ - if (H5F_low_extend(f->shared->lf, f->shared->access_parms, op, - size, addr/*out*/) < 0) { - HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, - "low level mem management failed"); + for (i=0, found=-1; ishared->fl_nfree; i++) { + if ((status=H5F_low_alloc(f->shared->lf, op, align, thresh, size, + f->shared->fl_free+i, addr/*out*/))>0) { + /* Exact match found */ + found = i; + break; + } else if (0==status) { + /* Partial match */ + found = i; + } } - /* Convert from absolute to relative */ - addr->offset -= f->shared->base_addr.offset; - - /* Did we extend the size of the hdf5 data? */ - tmp_addr = *addr; - H5F_addr_inc(&tmp_addr, size); - if (H5F_addr_gt(&tmp_addr, &(f->shared->hdf5_eof))) { - f->shared->hdf5_eof = tmp_addr; + + if (found>=0 && + (status=H5F_low_alloc (f->shared->lf, op, align, thresh, size, + f->shared->fl_free+found, addr/*out*/))>0) { + /* + * We found an exact match. Remove that block from the free list and + * use it to satisfy the request. + */ + --(f->shared->fl_nfree); + HDmemmove (f->shared->fl_free+found, f->shared->fl_free+found+1, + (f->shared->fl_nfree-found) * sizeof(H5MF_free_t)); + + } else if (found>=0 && status==0) { + /* + * We found a free block which is larger than the requested size. + * Return the unused parts of the free block to the free list. + */ + blk = f->shared->fl_free[found]; + --f->shared->fl_nfree; + HDmemmove (f->shared->fl_free+found, f->shared->fl_free+found+1, + (f->shared->fl_nfree-found) * sizeof(H5MF_free_t)); + if (H5F_addr_gt (addr, &(blk.addr))) { + /* Free the first part of the free block */ + n = addr->offset - blk.addr.offset; + H5MF_free (f, &(blk.addr), n); + blk.addr = *addr; + blk.size -= n; + } + + if (blk.size > size) { + /* Free the second part of the free block */ + H5F_addr_inc (&(blk.addr), size); + blk.size -= size; + H5MF_free (f, &(blk.addr), blk.size); + } + + } else { + /* + * No suitable free block was found. Allocate space from the end of + * the file. We don't know about alignment at this point, so we + * allocate enough space to align the data also. + */ + if (size>=thresh) { + blk.size = size + align - 1; + } else { + blk.size = size; + } + if (H5F_low_extend(f->shared->lf, f->shared->access_parms, op, + blk.size, &(blk.addr)/*out*/) < 0) { + HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "low level mem management failed"); + } + + /* Convert from absolute to relative */ + blk.addr.offset -= f->shared->base_addr.offset; + + /* Did we extend the size of the hdf5 data? */ + tmp_addr = blk.addr; + H5F_addr_inc(&tmp_addr, blk.size); + if (H5F_addr_gt(&tmp_addr, &(f->shared->hdf5_eof))) { + f->shared->hdf5_eof = tmp_addr; + } + + if ((status=H5F_low_alloc (f->shared->lf, op, align, thresh, size, + &blk, addr/*out*/))>0) { + /* Exact match */ + } else if (0==status) { + /* Partial match */ + if (H5F_addr_gt (addr, &(blk.addr))) { + n = addr->offset - blk.addr.offset; + H5MF_free (f, &(blk.addr), n); + blk.addr = *addr; + blk.size -= n; + } + if (blk.size > size) { + H5F_addr_inc (&(blk.addr), size); + blk.size -= size; + H5MF_free (f, &(blk.addr), blk.size); + } + } } + FUNC_LEAVE(SUCCEED); } @@ -111,8 +204,10 @@ H5MF_alloc(H5F_t *f, intn op, hsize_t size, haddr_t *addr/*out*/) *------------------------------------------------------------------------- */ herr_t -H5MF_free(H5F_t __unused__ *f, const haddr_t *addr, hsize_t size) +H5MF_free(H5F_t *f, const haddr_t *addr, hsize_t size) { + int i; + FUNC_ENTER(H5MF_free, FAIL); /* check arguments */ @@ -121,11 +216,29 @@ H5MF_free(H5F_t __unused__ *f, const haddr_t *addr, hsize_t size) HRETURN(SUCCEED); assert(!H5F_addr_zerop(addr)); + /* + * Insert this free block into the free list without attempting to + * combine it with other free blocks. If the list is overfull then + * remove the smallest free block. + */ + if (f->shared->fl_nfree>=H5MF_NFREE) { + for (i=0; ishared->fl_free[i].sizeshared->fl_free[i].size); #endif - + f->shared->fl_free[i].addr = *addr; + f->shared->fl_free[i].size = size; + break; + } + } + } else { + i = f->shared->fl_nfree++; + f->shared->fl_free[i].addr = *addr; + f->shared->fl_free[i].size = size; + } + FUNC_LEAVE(SUCCEED); } diff --git a/src/H5P.c b/src/H5P.c index aa11f08..095bfa9 100644 --- a/src/H5P.c +++ b/src/H5P.c @@ -515,6 +515,102 @@ H5Pget_userblock(hid_t tid, hsize_t *size) FUNC_LEAVE(SUCCEED); } + + +/*------------------------------------------------------------------------- + * Function: H5Pset_alignment + * + * Purpose: Sets the alignment properties of a file access property list + * so that any file object >= THRESHOLD bytes will be aligned on + * an address which is a multiple of ALIGNMENT. The addresses + * are relative to the end of the user block; the alignment is + * calculated by subtracting the user block size from the + * absolute file address and then adjusting the address to be a + * multiple of ALIGNMENT. + * + * Default values for THRESHOLD and ALIGNMENT are one, implying + * no alignment. Generally the default values will result in + * the best performance for single-process access to the file. + * For MPI-IO and other parallel systems, choose an alignment + * which is a multiple of the disk block size. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, June 9, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_alignment (hid_t fapl_id, hsize_t threshold, hsize_t alignment) +{ + H5F_access_t *fapl = NULL; + + FUNC_ENTER (H5Pset_alignment, FAIL); + + /* Check args */ + if (H5P_FILE_ACCESS != H5Pget_class (fapl_id) || + NULL == (fapl = H5I_object (fapl_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access property list"); + } + if (alignment<1) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "alignment must be positive"); + } + + /* Set values */ + fapl->threshold = threshold; + fapl->alignment = alignment; + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5Pget_alignment + * + * Purpose: Returns the current settings for alignment properties from a + * file access property list. The THRESHOLD and/or ALIGNMENT + * pointers may be null pointers. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, June 9, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_alignment (hid_t fapl_id, hsize_t *threshold/*out*/, + hsize_t *alignment/*out*/) +{ + H5F_access_t *fapl = NULL; + + FUNC_ENTER (H5Pget_alignment, FAIL); + + /* Check args */ + if (H5P_FILE_ACCESS != H5Pget_class (fapl_id) || + NULL == (fapl = H5I_object (fapl_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access property list"); + } + + /* Get values */ + if (threshold) *threshold = fapl->threshold; + if (alignment) *alignment = fapl->alignment; + + FUNC_LEAVE (SUCCEED); +} + /*------------------------------------------------------------------------- * Function: H5Pset_sizes @@ -2211,8 +2307,6 @@ herr_t H5Pset_mpi (hid_t tid, MPI_Comm comm, MPI_Info info) { H5F_access_t *tmpl = NULL; - MPI_Comm lcomm; - int mrc; /* MPI return code */ FUNC_ENTER(H5Pset_mpi, FAIL); diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 9a3cda2..220073f 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -51,6 +51,9 @@ herr_t H5Pget_version (hid_t tid, int *boot/*out*/, int *freelist/*out*/, int *stab/*out*/, int *shhdr/*out*/); herr_t H5Pset_userblock (hid_t tid, hsize_t size); herr_t H5Pget_userblock (hid_t tid, hsize_t *size); +herr_t H5Pset_alignment (hid_t fapl_id, hsize_t threshold, hsize_t alignment); +herr_t H5Pget_alignment (hid_t fapl_id, hsize_t *threshold/*out*/, + hsize_t *alignment/*out*/); herr_t H5Pset_sizes (hid_t tid, size_t sizeof_addr, size_t sizeof_size); herr_t H5Pget_sizes (hid_t tid, size_t *sizeof_addr/*out*/, size_t *sizeof_size/*out*/); diff --git a/src/H5S.c b/src/H5S.c index 771ccba..0d44675 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -813,18 +813,19 @@ H5S_modify(H5G_entry_t *ent, const H5S_t *ds) * Tuesday, December 9, 1997 * * Modifications: - * + * Robb Matzke, 9 Jun 1998 + * Removed the unused file argument since the file is now part of the + * ENT argument. *------------------------------------------------------------------------- */ H5S_t * -H5S_read(H5F_t __unused__ *f, H5G_entry_t *ent) +H5S_read(H5G_entry_t *ent) { H5S_t *ds = NULL; FUNC_ENTER(H5S_read, NULL); /* check args */ - assert(f); assert(ent); ds = H5MM_xcalloc(1, sizeof(H5S_t)); diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 06e9d0f..084c282 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -118,7 +118,7 @@ intn H5S_get_ndims (const H5S_t *ds); intn H5S_get_dims (const H5S_t *ds, hsize_t dims[]/*out*/, hsize_t max_dims[]/*out*/); herr_t H5S_modify (H5G_entry_t *ent, const H5S_t *space); -H5S_t *H5S_read (H5F_t *f, H5G_entry_t *ent); +H5S_t *H5S_read (H5G_entry_t *ent); intn H5S_cmp (const H5S_t *ds1, const H5S_t *ds2); hbool_t H5S_is_simple (const H5S_t *sdim); uintn H5S_nelem (const H5S_t *space); diff --git a/test/.distdep b/test/.distdep index 349d760..991f255 100644 --- a/test/.distdep +++ b/test/.distdep @@ -41,8 +41,8 @@ tfile.o: \ ../src/H5Bpublic.h \ ../src/H5Fprivate.h \ ../src/H5Fpublic.h \ - ../src/H5Pprivate.h \ - ../src/H5Ppublic.h + ../src/H5Dpublic.h \ + ../src/H5Pprivate.h theap.o: \ theap.c \ testhdf5.h \ @@ -57,9 +57,9 @@ theap.o: \ ../src/H5ACpublic.h \ ../src/H5Fprivate.h \ ../src/H5Fpublic.h \ + ../src/H5Dpublic.h \ ../src/H5Pprivate.h \ ../src/H5Ppublic.h \ - ../src/H5Dpublic.h \ ../src/H5Zpublic.h tmeta.o: \ tmeta.c \ @@ -84,9 +84,9 @@ tohdr.o: \ ../src/H5ACpublic.h \ ../src/H5Fprivate.h \ ../src/H5Fpublic.h \ + ../src/H5Dpublic.h \ ../src/H5Pprivate.h \ ../src/H5Ppublic.h \ - ../src/H5Dpublic.h \ ../src/H5Zpublic.h \ ../src/H5Gprivate.h \ ../src/H5Gpublic.h \ @@ -114,9 +114,9 @@ tstab.o: \ ../src/H5ACpublic.h \ ../src/H5Fprivate.h \ ../src/H5Fpublic.h \ + ../src/H5Dpublic.h \ ../src/H5Pprivate.h \ ../src/H5Ppublic.h \ - ../src/H5Dpublic.h \ ../src/H5Zpublic.h \ ../src/H5Gprivate.h \ ../src/H5Gpublic.h \ @@ -143,6 +143,7 @@ th5s.o: \ ../src/H5Bpublic.h \ ../src/H5Fprivate.h \ ../src/H5Fpublic.h \ + ../src/H5Dpublic.h \ ../src/H5Sprivate.h \ ../src/H5Spublic.h \ ../src/H5Gprivate.h \ @@ -155,8 +156,7 @@ th5s.o: \ ../src/H5Tpublic.h \ ../src/H5Zprivate.h \ ../src/H5Zpublic.h \ - ../src/H5Pprivate.h \ - ../src/H5Ppublic.h + ../src/H5Pprivate.h dtypes.o: \ dtypes.c \ ../src/hdf5.h \ @@ -328,13 +328,13 @@ gheap.o: \ ../src/H5Ipublic.h \ ../src/H5Fprivate.h \ ../src/H5Fpublic.h \ + ../src/H5Dpublic.h \ ../src/H5Gprivate.h \ ../src/H5Gpublic.h \ ../src/H5Bprivate.h \ ../src/H5Bpublic.h \ ../src/H5HGprivate.h \ - ../src/H5HGpublic.h \ - ../src/H5Pprivate.h + ../src/H5HGpublic.h shtype.o: \ shtype.c \ ../src/hdf5.h \ @@ -397,7 +397,10 @@ links.o: \ ../src/H5MFpublic.h \ ../src/H5MMpublic.h \ ../src/H5Opublic.h \ - ../src/H5Ppublic.h + ../src/H5Ppublic.h \ + ../src/H5Zpublic.h \ + ../src/H5Spublic.h \ + ../src/H5Tpublic.h chunk.o: \ chunk.c \ ../src/hdf5.h \ diff --git a/test/dsets.c b/test/dsets.c index fac3bdb..576a575 100644 --- a/test/dsets.c +++ b/test/dsets.c @@ -670,6 +670,77 @@ test_compression(hid_t file) error: return -1; } + + +/*------------------------------------------------------------------------- + * Function: test_multiopen + * + * Purpose: Tests that a bug no longer exists. If a dataset is opened + * twice and one of the handles is used to extend the dataset, + * then the other handle should return the new size when + * queried. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * Tuesday, June 9, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +test_multiopen (hid_t file) +{ + hid_t dcpl, space, dset1, dset2; + hsize_t cur_size[1] = {10}; + static hsize_t max_size[1] = {H5S_UNLIMITED}; + hsize_t tmp_size[1]; + + printf ("%-70s", "Testing multi-open with extending"); + + /* Create the dataset and open it twice */ + if ((dcpl=H5Pcreate (H5P_DATASET_CREATE))<0) goto error; + if (H5Pset_chunk (dcpl, 1, cur_size)<0) goto error; + if ((space=H5Screate_simple (1, cur_size, max_size))<0) goto error; + if ((dset1=H5Dcreate (file, "multiopen", H5T_NATIVE_INT, space, + dcpl))<0) goto error; + if ((dset2=H5Dopen (file, "multiopen"))<0) goto error; + if (H5Sclose (space)<0) goto error; + + /* Extend with the first handle */ + cur_size[0] = 20; + if (H5Dextend (dset1, cur_size)<0) goto error; + + /* Get the size from the second handle */ + if ((space = H5Dget_space (dset2))<0) goto error; + if (H5Sget_dims (space, tmp_size)<0) goto error; + if (cur_size[0]!=tmp_size[0]) { + puts ("*FAILED*"); + printf (" Got %d instead of %d!\n", + (int)tmp_size[0], (int)cur_size[0]); + goto error; + } + + if (H5Dclose (dset1)<0) goto error; + if (H5Dclose (dset2)<0) goto error; + if (H5Sclose (space)<0) goto error; + if (H5Pclose (dcpl)<0) goto error; + puts (" PASSED"); + return 0; + + error: + H5E_BEGIN_TRY { + H5Dclose (dset1); + H5Dclose (dset2); + H5Sclose (space); + H5Pclose (dcpl); + } H5E_END_TRY; + return -1; +} + /*------------------------------------------------------------------------- * Function: cleanup @@ -744,6 +815,9 @@ main(void) status = test_compression(file); nerrors += status < 0 ? 1 : 0; + status = test_multiopen (file); + nerrors += status < 0 ? 1 : 0; + status = H5Fclose(file); if (nerrors) { -- cgit v0.12