diff options
-rw-r--r-- | src/H5D.c | 97 | ||||
-rw-r--r-- | src/H5F.c | 2 | ||||
-rw-r--r-- | src/H5Fcore.c | 19 | ||||
-rw-r--r-- | src/H5Ffamily.c | 15 | ||||
-rw-r--r-- | src/H5Flow.c | 66 | ||||
-rw-r--r-- | src/H5Fmpio.c | 29 | ||||
-rw-r--r-- | src/H5Fprivate.h | 21 | ||||
-rw-r--r-- | src/H5Fsec2.c | 5 | ||||
-rw-r--r-- | src/H5Fsplit.c | 90 | ||||
-rw-r--r-- | src/H5Fstdio.c | 5 | ||||
-rw-r--r-- | src/H5MF.c | 155 | ||||
-rw-r--r-- | src/H5P.c | 98 | ||||
-rw-r--r-- | src/H5Ppublic.h | 3 | ||||
-rw-r--r-- | src/H5S.c | 7 | ||||
-rw-r--r-- | src/H5Sprivate.h | 2 | ||||
-rw-r--r-- | test/.distdep | 23 | ||||
-rw-r--r-- | test/dsets.c | 74 |
17 files changed, 595 insertions, 116 deletions
@@ -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); } @@ -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; @@ -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 <H5private.h> @@ -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; i<f->shared->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; i<H5MF_NFREE; i++) { + if (f->shared->fl_free[i].size<size) { #ifdef H5MF_DEBUG - fprintf(stderr, "H5MF_free: lost %lu bytes of file storage\n", - (unsigned long) size); + fprintf(stderr, "H5MF_free: lost %lu bytes of file storage\n", + (unsigned long) f->shared->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); } @@ -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*/); @@ -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) { |