diff options
-rw-r--r-- | release_docs/RELEASE.txt | 3 | ||||
-rw-r--r-- | src/H5F.c | 1132 | ||||
-rw-r--r-- | src/H5Fpkg.h | 14 | ||||
-rw-r--r-- | src/H5Fsuper.c | 133 | ||||
-rw-r--r-- | src/H5G.c | 37 | ||||
-rw-r--r-- | src/H5Gprivate.h | 1 | ||||
-rw-r--r-- | src/H5T.c | 2 | ||||
-rw-r--r-- | src/Makefile.in | 2 | ||||
-rw-r--r-- | test/mount.c | 139 |
9 files changed, 268 insertions, 1195 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 095cb9e..5a87368 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -72,6 +72,9 @@ Bug Fixes since HDF5-1.6.4 release Library ------- + - Don't unmount child files until the parent file actually closes. + (Previously, if an object is holding open a file, the child files + would get unmounted too early). QAK - 2005/07/05 - Fixed bug where unmounted files could cause the library to go into an infinite loop when shutting down. QAK - 2005/06/30 - Fixed bug with hyperslab selections that use selection offsets and @@ -64,21 +64,15 @@ typedef struct H5F_olist_t { /* PRIVATE PROTOTYPES */ static H5F_t *H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id); -static herr_t H5F_close(H5F_t *f); #ifdef NOT_YET static herr_t H5F_flush_all(hbool_t invalidate); static int H5F_flush_all_cb(void *f, hid_t fid, void *_invalidate); #endif /* NOT_YET */ -static herr_t H5F_init_superblock(const H5F_t *f, hid_t dxpl_id); -static herr_t H5F_write_superblock(H5F_t *f, hid_t dxpl_id); -static herr_t H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent); - static H5F_t *H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id); static herr_t H5F_dest(H5F_t *f, hid_t dxpl_id); static herr_t H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags); -static haddr_t H5F_locate_signature(H5FD_t *file, hid_t dxpl_id); static int H5F_get_objects(const H5F_t *f, unsigned types, int max_objs, hid_t *obj_id_list); static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key); static herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void** file_handle); @@ -401,53 +395,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_term_unmount_cb - * - * Purpose: H5F_term_interface' callback function. This routine - * unmounts child files from files that are in the "closing" - * state. - * - * Programmer: Quincey Koziol - * Thursday, Jun 30, 2005 - * - * Modification: - * - *------------------------------------------------------------------------- - */ -static int -H5F_term_unmount_cb(void *obj_ptr, hid_t obj_id, void UNUSED *key) -{ - H5F_t *f = (H5F_t *)obj_ptr; /* Alias for search info */ - unsigned u; /* Local index */ - int ret_value = FALSE; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5F_term_unmount_cb) - - assert(f); - - if(f->mtab.nmounts) { - /* Unmount all child files */ - for (u=0; u<f->mtab.nmounts; u++) { - f->mtab.child[u].file->mtab.parent = NULL; - if(H5G_close(f->mtab.child[u].group)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close child group") - if(H5F_close(f->mtab.child[u].file)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close child file") - } /* end if */ - f->mtab.nmounts = 0; - - /* Decrement reference count for file */ - H5I_dec_ref(obj_id); - } /* end if */ - else - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "no files to unmount") - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_term_unmount_cb() */ - - -/*------------------------------------------------------------------------- * Function: H5F_term_interface * * Purpose: Terminate this interface: free all memory and reset global @@ -1337,7 +1284,7 @@ H5F_equal(void *_haystack, hid_t UNUSED id, void *_needle) * Rewritten to use the virtual file layer. *------------------------------------------------------------------------- */ -static haddr_t +haddr_t H5F_locate_signature(H5FD_t *file, hid_t dxpl_id) { haddr_t addr, eoa; @@ -2022,7 +1969,6 @@ done: hid_t H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id) { - H5F_t *new_file = NULL; /*file struct for new file */ hid_t ret_value; /*return value */ @@ -2249,537 +2195,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_read_superblock - * - * Purpose: Reads the superblock from the file or from the BUF. If - * ADDR is a valid address, then it reads it from the file. - * If not, then BUF must be non-NULL for it to read from the - * BUF. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Bill Wendling - * wendling@ncsa.uiuc.edu - * Sept 12, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent) -{ - haddr_t stored_eoa; /*relative end-of-addr in file */ - haddr_t eof; /*end of file address */ - uint8_t *q; /*ptr into temp I/O buffer */ - size_t sizeof_addr = 0; - size_t sizeof_size = 0; - const size_t fixed_size = 24; /*fixed sizeof superblock */ - unsigned sym_leaf_k = 0; - size_t variable_size; /*variable sizeof superblock */ - unsigned btree_k[H5B_NUM_BTREE_ID]; /* B-tree internal node 'K' values */ - H5F_file_t *shared = NULL; /* shared part of `file' */ - H5FD_t *lf = NULL; /* file driver part of `shared' */ - uint8_t *p; /* Temporary pointer into encoding buffers */ - unsigned i; /* Index variable */ - unsigned chksum; /* Checksum temporary variable */ - size_t driver_size; /* Size of driver info block, in bytes */ - char driver_name[9]; /* Name of driver, for driver info block */ - unsigned super_vers; /* Super block version */ - unsigned freespace_vers; /* Freespace info version */ - unsigned obj_dir_vers; /* Object header info version */ - unsigned share_head_vers; /* Shared header info version */ - uint8_t buf[H5F_SUPERBLOCK_SIZE]; /* Local buffer */ - H5P_genplist_t *c_plist; /* File creation property list */ - herr_t ret_value = SUCCEED; - - /* Decoding */ - FUNC_ENTER_NOAPI(H5F_read_superblock, FAIL) - - /* Short cuts */ - shared = f->shared; - lf = shared->lf; - - /* Get the shared file creation property list */ - if (NULL == (c_plist = H5I_object(shared->fcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") - - /* Read the superblock if it hasn't been read before. */ - if (HADDR_UNDEF == (shared->super_addr=H5F_locate_signature(lf,dxpl_id))) - HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to find file signature") - if (H5FD_set_eoa(lf, shared->super_addr + fixed_size) < 0 || - H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr, fixed_size, buf) < 0) - HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "unable to read superblock") - - /* Signature, already checked */ - p = buf + H5F_SIGNATURE_LEN; - - /* Superblock version */ - super_vers = *p++; - if (super_vers > HDF5_SUPERBLOCK_VERSION_MAX) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad superblock version number") - if (H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set superblock version") - - /* Freespace version */ - freespace_vers = *p++; - if (HDF5_FREESPACE_VERSION != freespace_vers) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad free space version number") - if (H5P_set(c_plist, H5F_CRT_FREESPACE_VERS_NAME, &freespace_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to free space version") - - /* Root group version number */ - obj_dir_vers = *p++; - if (HDF5_OBJECTDIR_VERSION != obj_dir_vers) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad object directory version number") - if (H5P_set(c_plist, H5F_CRT_OBJ_DIR_VERS_NAME, &obj_dir_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set object directory version") - - /* Skip over reserved byte */ - p++; - - /* Shared header version number */ - share_head_vers = *p++; - if (HDF5_SHAREDHEADER_VERSION != share_head_vers) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad shared-header format version number") - if (H5P_set(c_plist, H5F_CRT_SHARE_HEAD_VERS_NAME, &share_head_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set shared-header format version") - - /* Size of file addresses */ - sizeof_addr = *p++; - if (sizeof_addr != 2 && sizeof_addr != 4 && - sizeof_addr != 8 && sizeof_addr != 16 && sizeof_addr != 32) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number in an address") - if (H5P_set(c_plist, H5F_CRT_ADDR_BYTE_NUM_NAME,&sizeof_addr) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set byte number in an address") - shared->sizeof_addr = sizeof_addr; /* Keep a local copy also */ - - /* Size of file sizes */ - sizeof_size = *p++; - if (sizeof_size != 2 && sizeof_size != 4 && - sizeof_size != 8 && sizeof_size != 16 && sizeof_size != 32) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad byte number for object size") - if (H5P_set(c_plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &sizeof_size) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set byte number for object size") - shared->sizeof_size = sizeof_size; /* Keep a local copy also */ - - /* Skip over reserved byte */ - p++; - - /* Various B-tree sizes */ - UINT16DECODE(p, sym_leaf_k); - if (sym_leaf_k == 0) - HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "bad symbol table leaf node 1/2 rank") - if (H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &sym_leaf_k) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set rank for symbol table leaf nodes") - shared->sym_leaf_k = sym_leaf_k; /* Keep a local copy also */ - - /* Need 'get' call to set other array values */ - if (H5P_get(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get rank for btree internal nodes") - UINT16DECODE(p, btree_k[H5B_SNODE_ID]); - if (btree_k[H5B_SNODE_ID] == 0) - HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "bad 1/2 rank for btree internal nodes") - /* - * Delay setting the value in the property list until we've checked - * for the indexed storage B-tree internal 'K' value later. - */ - - /* File consistency flags. Not really used yet */ - UINT32DECODE(p, shared->consist_flags); - assert(((size_t)(p - buf)) == fixed_size); - - /* Decode the variable-length part of the superblock... */ - variable_size = (super_vers>0 ? 4 : 0) + /* Potential indexed storage B-tree internal 'K' value */ - H5F_SIZEOF_ADDR(f) + /*base addr*/ - H5F_SIZEOF_ADDR(f) + /*global free list*/ - H5F_SIZEOF_ADDR(f) + /*end-of-address*/ - H5F_SIZEOF_ADDR(f) + /*reserved address*/ - H5G_SIZEOF_ENTRY(f); /*root group ptr*/ - assert(fixed_size + variable_size <= sizeof(buf)); - if (H5FD_set_eoa(lf, shared->super_addr + fixed_size+variable_size) < 0 || - H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr + fixed_size, variable_size, p) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read superblock") - - /* - * If the superblock version # is greater than 0, read in the indexed - * storage B-tree internal 'K' value - */ - if (super_vers > 0) { - UINT16DECODE(p, btree_k[H5B_ISTORE_ID]); - p += 2; /* reserved */ - } - else - btree_k[H5B_ISTORE_ID] = HDF5_BTREE_ISTORE_IK_DEF; - - /* Set the B-tree internal node values, etc */ - if (H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set rank for btree internal nodes") - HDmemcpy(shared->btree_k, btree_k, sizeof(unsigned) * (size_t)H5B_NUM_BTREE_ID); /* Keep a local copy also */ - - H5F_addr_decode(f, (const uint8_t **)&p, &shared->base_addr/*out*/); - H5F_addr_decode(f, (const uint8_t **)&p, &shared->freespace_addr/*out*/); - H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/); - H5F_addr_decode(f, (const uint8_t **)&p, &shared->driver_addr/*out*/); - if (H5G_ent_decode(f, (const uint8_t **)&p, root_ent/*out*/) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read root symbol entry") - - /* - * Check if superblock address is different from base address and - * adjust base address and "end of address" address if so. - */ - if (!H5F_addr_eq(shared->super_addr,shared->base_addr)) { - /* Check if the superblock moved earlier in the file */ - if (H5F_addr_lt(shared->super_addr, shared->base_addr)) - stored_eoa -= (shared->base_addr - shared->super_addr); - else - /* The superblock moved later in the file */ - stored_eoa += (shared->super_addr - shared->base_addr); - - shared->base_addr = shared->super_addr; - } /* end if */ - - /* Compute super block checksum */ - assert(sizeof(chksum) == sizeof(shared->super_chksum)); - for (q = (uint8_t *)&chksum, chksum = 0, i = 0; i < fixed_size + variable_size; ++i) - q[i % sizeof(shared->super_chksum)] ^= buf[i]; - - /* Set the super block checksum */ - shared->super_chksum = chksum; - - /* Decode the optional driver information block */ - if (H5F_addr_defined(shared->driver_addr)) { - haddr_t drv_addr = shared->base_addr + shared->driver_addr; - uint8_t dbuf[H5F_DRVINFOBLOCK_SIZE]; /* Local buffer */ - - if (H5FD_set_eoa(lf, drv_addr + 16) < 0 || - H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr, (size_t)16, dbuf) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read driver information block") - p = dbuf; - - /* Version number */ - if (HDF5_DRIVERINFO_VERSION != *p++) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "bad driver information block version number") - - p += 3; /* reserved */ - - /* Driver info size */ - UINT32DECODE(p, driver_size); - - /* Driver name and/or version */ - HDstrncpy(driver_name, (const char *)p, (size_t)8); - driver_name[8] = '\0'; - p += 8; /* advance past name/version */ - - /* Read driver information and decode */ - assert((driver_size + 16) <= sizeof(dbuf)); - if (H5FD_set_eoa(lf, drv_addr + 16 + driver_size) < 0 || - H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr+16, driver_size, p) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read file driver information") - - if (H5FD_sb_decode(lf, driver_name, p) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to decode driver information") - - /* Compute driver info block checksum */ - assert(sizeof(chksum) == sizeof(shared->drvr_chksum)); - for (q = (uint8_t *)&chksum, chksum = 0, i = 0; i < (driver_size + 16); ++i) - q[i % sizeof(shared->drvr_chksum)] ^= dbuf[i]; - - /* Set the driver info block checksum */ - shared->drvr_chksum = chksum; - } /* end if */ - - /* - * The user-defined data is the area of the file before the base - * address. - */ - if (H5P_set(c_plist, H5F_CRT_USER_BLOCK_NAME, &shared->base_addr) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set usr block size") - - /* - * Make sure that the data is not truncated. One case where this is - * possible is if the first file of a family of files was opened - * individually. - */ - if (HADDR_UNDEF == (eof = H5FD_get_eof(lf))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size") - if (eof < stored_eoa) - HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, FAIL, "truncated file") - - /* - * Tell the file driver how much address space has already been - * allocated so that it knows how to allocate additional memory. - */ - if (H5FD_set_eoa(lf, stored_eoa) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to set end-of-address marker for file") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5F_init_superblock - * - * Purpose: Allocates the superblock for the file and initializes - * information about the superblock in memory. Does not write - * any superblock information to the file. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Sept 15, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5F_init_superblock(const H5F_t *f, hid_t dxpl_id) -{ - hsize_t userblock_size = 0; /* Size of userblock, in bytes */ - size_t superblock_size; /* Size of superblock, in bytes */ - size_t driver_size; /* Size of driver info block (bytes)*/ - unsigned super_vers; /* Super block version */ - haddr_t addr; /* Address of superblock */ - H5P_genplist_t *plist; /* Property list */ - herr_t ret_value=SUCCEED; - - /* Encoding */ - FUNC_ENTER_NOAPI(H5F_init_superblock, FAIL) - - /* Get the shared file creation property list */ - if (NULL == (plist = H5I_object(f->shared->fcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") - - /* - * The superblock starts immediately after the user-defined - * header, which we have already insured is a proper size. The - * base address is set to the same thing as the superblock for - * now. - */ - if(H5P_get(plist, H5F_CRT_USER_BLOCK_NAME, &userblock_size) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get user block size") - f->shared->super_addr = userblock_size; - f->shared->base_addr = f->shared->super_addr; - f->shared->consist_flags = 0x03; - - /* Grab superblock version from property list */ - if (H5P_get(plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get super block version") - - /* Compute the size of the superblock */ - superblock_size=H5F_SIGNATURE_LEN /* Signature length (8 bytes) */ - + 16 /* Length of required fixed-size portion */ - + ((super_vers>0) ? 4 : 0) /* Version specific fixed-size portion */ - + 4 * H5F_sizeof_addr(f) /* Variable-sized addresses */ - + H5G_SIZEOF_ENTRY(f); /* Size of root group symbol table entry */ - - /* Compute the size of the driver information block. */ - H5_ASSIGN_OVERFLOW(driver_size, H5FD_sb_size(f->shared->lf), hsize_t, size_t); - if (driver_size > 0) - driver_size += 16; /* Driver block header */ - - /* - * Allocate space for the userblock, superblock, and driver info - * block. We do it with one allocation request because the - * userblock and superblock need to be at the beginning of the - * file and only the first allocation request is required to - * return memory at format address zero. - */ - - H5_CHECK_OVERFLOW(f->shared->base_addr, haddr_t, hsize_t); - addr = H5FD_alloc(f->shared->lf, H5FD_MEM_SUPER, dxpl_id, - ((hsize_t)f->shared->base_addr + superblock_size + driver_size)); - - if (HADDR_UNDEF == addr) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, - "unable to allocate file space for userblock and/or superblock") - - if (0 != addr) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, - "file driver failed to allocate userblock and/or superblock at address zero") - - /* - * The file driver information block begins immediately after the - * superblock. - */ - if (driver_size > 0) - f->shared->driver_addr = superblock_size; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_init_superblock() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_write_superblock - * - * Purpose: Writes (and optionally allocates) the superblock for the file. - * If BUF is non-NULL, then write the serialized superblock - * information into it. It should be a buffer of size - * H5F_SUPERBLOCK_SIZE + H5F_DRVINFOBLOCK_SIZE or larger. - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Bill Wendling - * wendling@ncsa.uiuc.edu - * Sept 12, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5F_write_superblock(H5F_t *f, hid_t dxpl_id) -{ - uint8_t sbuf[H5F_SUPERBLOCK_SIZE]; /* Superblock encoding buffer */ - uint8_t dbuf[H5F_DRVINFOBLOCK_SIZE];/* Driver info block encoding buffer*/ - uint8_t *p = NULL; /* Ptr into encoding buffers */ - unsigned i; /* Index variable */ - unsigned chksum; /* Checksum temporary variable */ - size_t superblock_size; /* Size of superblock, in bytes */ - size_t driver_size; /* Size of driver info block (bytes)*/ - char driver_name[9]; /* Name of driver, for driver info block */ - unsigned super_vers; /* Super block version */ - unsigned freespace_vers; /* Freespace info version */ - unsigned obj_dir_vers; /* Object header info version */ - unsigned share_head_vers; /* Shared header info version */ - H5P_genplist_t *plist; /* Property list */ - herr_t ret_value = SUCCEED; - - /* Encoding */ - FUNC_ENTER_NOAPI(H5F_write_superblock, FAIL) - - /* Get the shared file creation property list */ - if (NULL == (plist = H5I_object(f->shared->fcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") - - /* Grab values from property list */ - if (H5P_get(plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get super block version") - if (H5P_get(plist, H5F_CRT_FREESPACE_VERS_NAME, &freespace_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get free space version") - if (H5P_get(plist, H5F_CRT_OBJ_DIR_VERS_NAME, &obj_dir_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get object directory version") - if (H5P_get(plist, H5F_CRT_SHARE_HEAD_VERS_NAME, &share_head_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get shared-header format version") - - /* Encode the file super block */ - p = sbuf; - HDmemcpy(p, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN); - p += H5F_SIGNATURE_LEN; - *p++ = (uint8_t)super_vers; - *p++ = (uint8_t)freespace_vers; - *p++ = (uint8_t)obj_dir_vers; - *p++ = 0; /* reserved*/ - *p++ = (uint8_t)share_head_vers; - assert (H5F_SIZEOF_ADDR(f) <= 255); - *p++ = (uint8_t)H5F_SIZEOF_ADDR(f); - assert (H5F_SIZEOF_SIZE(f) <= 255); - *p++ = (uint8_t)H5F_SIZEOF_SIZE(f); - *p++ = 0; /* reserved */ - UINT16ENCODE(p, f->shared->sym_leaf_k); - UINT16ENCODE(p, f->shared->btree_k[H5B_SNODE_ID]); - UINT32ENCODE(p, f->shared->consist_flags); - - /* - * Versions of the superblock >0 have the indexed storage B-tree - * internal 'K' value stored - */ - if (super_vers > 0) { - UINT16ENCODE(p, f->shared->btree_k[H5B_ISTORE_ID]); - *p++ = 0; /*reserved */ - *p++ = 0; /*reserved */ - } - - H5F_addr_encode(f, &p, f->shared->base_addr); - H5F_addr_encode(f, &p, f->shared->freespace_addr); - H5F_addr_encode(f, &p, H5FD_get_eoa(f->shared->lf)); - H5F_addr_encode(f, &p, f->shared->driver_addr); - if(H5G_ent_encode(f, &p, H5G_entof(f->shared->root_grp))<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode root group information") - - H5_ASSIGN_OVERFLOW(superblock_size, p - sbuf, int, size_t); - - /* Double check we didn't overrun the block (unlikely) */ - assert(superblock_size <= sizeof(sbuf)); - - /* Encode the driver information block. */ - H5_ASSIGN_OVERFLOW(driver_size, H5FD_sb_size(f->shared->lf), hsize_t, size_t); - - if (driver_size > 0) { - driver_size += 16; /* Driver block header */ - - /* Double check we didn't overrun the block (unlikely) */ - assert(driver_size <= sizeof(dbuf)); - - /* Encode the driver information block */ - p = dbuf; - - *p++ = HDF5_DRIVERINFO_VERSION; /* Version */ - *p++ = 0; /* reserved */ - *p++ = 0; /* reserved */ - *p++ = 0; /* reserved */ - - /* Driver info size, excluding header */ - UINT32ENCODE(p, driver_size - 16); - - /* Encode driver-specific data */ - if (H5FD_sb_encode(f->shared->lf, driver_name, dbuf + 16) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information") - - /* Driver name */ - HDmemcpy(dbuf + 8, driver_name, (size_t)8); - } /* end if */ - - /* Compute super block checksum */ - assert(sizeof(chksum) == sizeof(f->shared->super_chksum)); - - for (p = (uint8_t *)&chksum, chksum = 0, i = 0; i < superblock_size; ++i) - p[i % sizeof(f->shared->super_chksum)] ^= sbuf[i]; - - /* Compare with current checksums */ - if (chksum != f->shared->super_chksum) { - /* Write superblock */ - if (H5FD_write(f->shared->lf, H5FD_MEM_SUPER, dxpl_id, - f->shared->super_addr, superblock_size, sbuf) < 0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write superblock") - - /* Update checksum information if different */ - f->shared->super_chksum = chksum; - } /* end if */ - - /* Check for driver info block */ - if (HADDR_UNDEF != f->shared->driver_addr) { - /* Compute driver info block checksum */ - assert(sizeof(chksum) == sizeof(f->shared->drvr_chksum)); - - for (p = (uint8_t *)&chksum, chksum = 0, i = 0; i < driver_size; ++i) - p[i % sizeof(f->shared->drvr_chksum)] ^= dbuf[i]; - - /* Compare with current checksums */ - if (chksum != f->shared->drvr_chksum) { - /* Write driver information block */ - if (H5FD_write(f->shared->lf, H5FD_MEM_SUPER, dxpl_id, - f->shared->base_addr + f->shared->driver_addr, driver_size, dbuf) < 0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write driver information block") - - /* Update checksum information if different */ - f->shared->drvr_chksum = chksum; - } /* end if */ - } /* end if */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- * Function: H5F_flush * * Purpose: Flushes (and optionally invalidates) cached data plus the @@ -2962,10 +2377,9 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5F_close(H5F_t *f) { - unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5F_close) @@ -2992,19 +2406,6 @@ H5F_close(H5F_t *f) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open") /* - * Unmount and close each child before closing the current file. - */ - assert(NULL==f->mtab.parent); - for (u=0; u<f->mtab.nmounts; u++) { - f->mtab.child[u].file->mtab.parent = NULL; - if(H5G_close(f->mtab.child[u].group)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close child group") - if(H5F_close(f->mtab.child[u].file)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close child file") - } /* end if */ - f->mtab.nmounts = 0; - - /* * Close file according to close degree: * * H5F_CLOSE_WEAK: if there are still objects open, wait until @@ -3035,6 +2436,26 @@ H5F_close(H5F_t *f) 1 == f->nopen_objs?"that header is":"those headers are"); } #endif + /* If the only open objects are the groups that are mount points, */ + /* allow the file to close and shut things down */ + if(f->nopen_objs == f->mtab.nmounts) { + unsigned u; /* Local index variable */ + hbool_t really_close; /* Whether to delay the file close by going to a "closing" state */ + + /* Check for open groups on mount points */ + really_close = TRUE; + for(u = 0; u < f->mtab.nmounts; u++) { + if(H5G_get_shared_count(f->mtab.child[u].group) > 1) { + really_close = FALSE; + break; + } /* end if */ + } /* end for */ + + /* If we really want to close this file now */ + if(really_close) + break; + } /* end if */ + /* Register an ID for closing the file later */ if (!f->closing) f->closing = H5I_register(H5I_FILE_CLOSING, f); @@ -3107,6 +2528,13 @@ H5F_close(H5F_t *f) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree") } /* end switch */ + /* + * Unmount and close each child before closing the current file. + */ + assert(NULL==f->mtab.parent); + if(H5F_close_mounts(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child file") + /* Invalidate file ID */ f->file_id = -1; @@ -3184,490 +2612,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_mount - * - * Purpose: Mount file CHILD onto the group specified by LOC and NAME, - * using mount properties in PLIST. CHILD must not already be - * mouted and must not be a mount ancestor of the mount-point. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Tuesday, October 6, 1998 - * - * Modifications: - * - * Robb Matzke, 1998-10-14 - * The reference count for the mounted H5F_t is incremented. - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * - *------------------------------------------------------------------------- - */ -static herr_t -H5F_mount(H5G_entry_t *loc, const char *name, H5F_t *child, - hid_t UNUSED plist_id, hid_t dxpl_id) -{ - H5G_t *mount_point = NULL; /*mount point group */ - H5G_entry_t *mp_ent = NULL; /*mount point symbol table entry*/ - H5F_t *ancestor = NULL; /*ancestor files */ - H5F_t *parent = NULL; /*file containing mount point */ - unsigned lt, rt, md; /*binary search indices */ - int cmp; /*binary search comparison value*/ - H5G_entry_t *ent = NULL; /*temporary symbol table entry */ - H5G_entry_t mp_open_ent; /* entry of moint point to be opened */ - H5RS_str_t *name_r; /* Ref-counted version of name */ - herr_t ret_value = SUCCEED; /*return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5F_mount) - - assert(loc); - assert(name && *name); - assert(child); - assert(TRUE==H5P_isa_class(plist_id,H5P_MOUNT)); - - /* - * Check that the child isn't mounted, that the mount point exists, and - * that the mount wouldn't introduce a cycle in the mount tree. - */ - if (child->mtab.parent) - HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "file is already mounted") - if (H5G_find(loc, name, NULL, &mp_open_ent/*out*/, H5AC_dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found") - if (NULL==(mount_point=H5G_open(&mp_open_ent, dxpl_id))) - HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found") - - parent = H5G_fileof(mount_point); - mp_ent = H5G_entof(mount_point); - for (ancestor=parent; ancestor; ancestor=ancestor->mtab.parent) { - if (ancestor==child) - HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount would introduce a cycle") - } - - /* - * Use a binary search to locate the position that the child should be - * inserted into the parent mount table. At the end of this paragraph - * `md' will be the index where the child should be inserted. - */ - lt = md = 0; - rt=parent->mtab.nmounts; - cmp = -1; - while (lt<rt && cmp) { - md = (lt+rt)/2; - ent = H5G_entof(parent->mtab.child[md].group); - cmp = H5F_addr_cmp(mp_ent->header, ent->header); - if (cmp<0) { - rt = md; - } else if (cmp>0) { - lt = md+1; - } - } - if (cmp>0) - md++; - if (!cmp) - HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point is already in use") - - /* Make room in the table */ - if (parent->mtab.nmounts>=parent->mtab.nalloc) { - unsigned n = MAX(16, 2*parent->mtab.nalloc); - H5F_mount_t *x = H5MM_realloc(parent->mtab.child, - n*sizeof(parent->mtab.child[0])); - if (!x) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for mount table") - parent->mtab.child = x; - parent->mtab.nalloc = n; - } - - /* Insert into table */ - HDmemmove(parent->mtab.child+md+1, parent->mtab.child+md, - (parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0])); - parent->mtab.nmounts++; - parent->mtab.child[md].group = mount_point; - parent->mtab.child[md].file = child; - child->mtab.parent = parent; - child->nrefs++; - - /* Search the open IDs and replace names for mount operation */ - /* We pass H5G_UNKNOWN as object type; search all IDs */ - name_r=H5RS_wrap(name); - assert(name_r); - if (H5G_replace_name( H5G_UNKNOWN, loc, name_r, NULL, NULL, NULL, OP_MOUNT )<0) - HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to replace name") - if(H5RS_decr(name_r)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "unable to decrement name string") - -done: - if (ret_value<0 && mount_point) - if(H5G_close(mount_point)<0) - HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close mounted group") - - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5F_unmount - * - * Purpose: Unmount the child which is mounted at the group specified by - * LOC and NAME or fail if nothing is mounted there. Neither - * file is closed. - * - * Because the mount point is specified by name and opened as a - * group, the H5G_namei() will resolve it to the root of the - * mounted file, not the group where the file is mounted. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Tuesday, October 6, 1998 - * - * Modifications: - * - * Robb Matzke, 1998-10-14 - * The ref count for the child is decremented by calling H5F_close(). - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * - *------------------------------------------------------------------------- - */ -static herr_t -H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id) -{ - H5G_t *mounted = NULL; /*mount point group */ - H5G_entry_t *mnt_ent = NULL; /*mounted symbol table entry */ - H5F_t *child = NULL; /*mounted file */ - H5F_t *parent = NULL; /*file where mounted */ - H5G_entry_t *ent = NULL; /*temporary symbol table entry */ - H5G_entry_t mnt_open_ent; /* entry used to open mount point*/ - herr_t ret_value = FAIL; /*return value */ - unsigned i; /*coutners */ - unsigned lt, rt, md=0; /*binary search indices */ - int cmp; /*binary search comparison value*/ - - FUNC_ENTER_NOAPI_NOINIT(H5F_unmount) - - assert(loc); - assert(name && *name); - - /* - * Get the mount point, or more precisely the root of the mounted file. - * If we get the root group and the file has a parent in the mount tree, - * then we must have found the mount point. - */ - if (H5G_find(loc, name, NULL, &mnt_open_ent/*out*/, H5AC_dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found") - if (NULL==(mounted=H5G_open(&mnt_open_ent, dxpl_id))) - HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found") - child = H5G_fileof(mounted); - mnt_ent = H5G_entof(mounted); - ent = H5G_entof(child->shared->root_grp); - - if (child->mtab.parent && - H5F_addr_eq(mnt_ent->header, ent->header)) { - /* - * We've been given the root group of the child. We do a reverse - * lookup in the parent's mount table to find the correct entry. - */ - parent = child->mtab.parent; - for (i=0; i<parent->mtab.nmounts; i++) { - if (parent->mtab.child[i].file==child) { - /* Search the open IDs replace names to reflect unmount operation */ - if (H5G_replace_name( H5G_UNKNOWN, mnt_ent, mnt_ent->user_path_r, NULL, NULL, NULL, OP_UNMOUNT )<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name ") - - /* Unmount the child */ - parent->mtab.nmounts -= 1; - if(H5G_close(parent->mtab.child[i].group)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group") - child->mtab.parent = NULL; - if(H5F_close(child)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file") - HDmemmove(parent->mtab.child+i, parent->mtab.child+i+1, - (parent->mtab.nmounts-i)* sizeof(parent->mtab.child[0])); - ret_value = SUCCEED; - } - } - assert(ret_value>=0); - - } else { - /* - * We've been given the mount point in the parent. We use a binary - * search in the parent to locate the mounted file, if any. - */ - parent = child; /*we guessed wrong*/ - lt = 0; - rt = parent->mtab.nmounts; - cmp = -1; - while (lt<rt && cmp) { - md = (lt+rt)/2; - ent = H5G_entof(parent->mtab.child[md].group); - cmp = H5F_addr_cmp(mnt_ent->header, ent->header); - if (cmp<0) { - rt = md; - } else { - lt = md+1; - } - } - if (cmp) - HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "not a mount point") - - /* Unmount the child */ - parent->mtab.nmounts -= 1; - if(H5G_close(parent->mtab.child[md].group)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group") - parent->mtab.child[md].file->mtab.parent = NULL; - if(H5F_close(parent->mtab.child[md].file)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file") - HDmemmove(parent->mtab.child+md, parent->mtab.child+md+1, - (parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0])); - ret_value = SUCCEED; - } - -done: - if (mounted) - if(H5G_close(mounted)<0 && ret_value>=0) - HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close group") - - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5F_mountpoint - * - * Purpose: If ENT is a mount point then copy the entry for the root - * group of the mounted file into ENT. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Tuesday, October 6, 1998 - * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_mountpoint(H5G_entry_t *find/*in,out*/) -{ - H5F_t *parent = find->file; - unsigned lt, rt, md=0; - int cmp; - H5G_entry_t *ent = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_mountpoint, FAIL) - - assert(find); - - /* - * The loop is necessary because we might have file1 mounted at the root - * of file2, which is mounted somewhere in file3. - */ - do { - /* - * Use a binary search to find the potential mount point in the mount - * table for the parent - */ - lt = 0; - rt = parent->mtab.nmounts; - cmp = -1; - while (lt<rt && cmp) { - md = (lt+rt)/2; - ent = H5G_entof(parent->mtab.child[md].group); - cmp = H5F_addr_cmp(find->header, ent->header); - if (cmp<0) { - rt = md; - } else { - lt = md+1; - } - } - - /* Copy root info over to ENT */ - if (0==cmp) { - /* Get the entry for the root group in the child's file */ - ent = H5G_entof(parent->mtab.child[md].file->shared->root_grp); - - /* Don't lose the user path of the group when we copy the root group's entry */ - if(H5G_ent_copy(find,ent,H5G_COPY_LIMITED)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy group entry") - - /* Switch to child's file */ - parent = ent->file; - } - } while (!cmp); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5F_has_mount - * - * Purpose: Check if a file has mounted files within it. - * - * Return: Success: TRUE/FALSE - * Failure: Negative - * - * Programmer: Quincey Koziol - * Thursday, January 2, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -htri_t -H5F_has_mount(const H5F_t *file) -{ - htri_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_has_mount, FAIL) - - assert(file); - - if(file->mtab.nmounts>0) - ret_value=TRUE; - else - ret_value=FALSE; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_has_mount() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_is_mount - * - * Purpose: Check if a file is mounted within another file. - * - * Return: Success: TRUE/FALSE - * Failure: Negative - * - * Programmer: Quincey Koziol - * Thursday, January 2, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -htri_t -H5F_is_mount(const H5F_t *file) -{ - htri_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_is_mount, FAIL) - - assert(file); - - if(file->mtab.parent!=NULL) - ret_value=TRUE; - else - ret_value=FALSE; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_is_mount() */ - - -/*------------------------------------------------------------------------- - * Function: H5Fmount - * - * Purpose: Mount file CHILD_ID onto the group specified by LOC_ID and - * NAME using mount properties PLIST_ID. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Tuesday, October 6, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id) -{ - H5G_entry_t *loc = NULL; - H5F_t *child = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Fmount, FAIL) - H5TRACE4("e","isii",loc_id,name,child_id,plist_id); - - /* Check arguments */ - if (NULL==(loc=H5G_loc(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") - if (NULL==(child=H5I_object_verify(child_id,H5I_FILE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") - if(H5P_DEFAULT == plist_id) - plist_id = H5P_MOUNT_DEFAULT; - else - if(TRUE != H5P_isa_class(plist_id, H5P_MOUNT)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not property list") - - /* Do the mount */ - if (H5F_mount(loc, name, child, plist_id, H5AC_dxpl_id)<0) - HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to mount file") - -done: - FUNC_LEAVE_API(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5Funmount - * - * Purpose: Given a mount point, dissassociate the mount point's file - * from the file mounted there. Do not close either file. - * - * The mount point can either be the group in the parent or the - * root group of the mounted file (both groups have the same - * name). If the mount point was opened before the mount then - * it's the group in the parent, but if it was opened after the - * mount then it's the root group of the child. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Tuesday, October 6, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Funmount(hid_t loc_id, const char *name) -{ - H5G_entry_t *loc = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Funmount, FAIL) - H5TRACE2("e","is",loc_id,name); - - /* Check args */ - if (NULL==(loc=H5G_loc(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") - - /* Unmount */ - if (H5F_unmount(loc, name, H5AC_dxpl_id)<0) - HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to unmount file") - -done: - FUNC_LEAVE_API(ret_value) -} - - -/*------------------------------------------------------------------------- * Function: H5Freopen * * Purpose: Reopen a file. The new file handle which is returned points @@ -3836,7 +2780,8 @@ H5F_sizeof_size(const H5F_t *f) * Added this header and removed unused ret_value variable. *------------------------------------------------------------------------- */ -unsigned H5F_sym_leaf_k(const H5F_t *f) +unsigned +H5F_sym_leaf_k(const H5F_t *f) { /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sym_leaf_k) @@ -3903,7 +2848,8 @@ H5F_Kvalue(const H5F_t *f, const H5B_class_t *type) * *------------------------------------------------------------------------- */ -size_t H5F_rdcc_nelmts(const H5F_t *f) +size_t +H5F_rdcc_nelmts(const H5F_t *f) { /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nelmts) @@ -3935,7 +2881,8 @@ size_t H5F_rdcc_nelmts(const H5F_t *f) * *------------------------------------------------------------------------- */ -size_t H5F_rdcc_nbytes(const H5F_t *f) +size_t +H5F_rdcc_nbytes(const H5F_t *f) { /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nbytes) @@ -3967,7 +2914,8 @@ size_t H5F_rdcc_nbytes(const H5F_t *f) * *------------------------------------------------------------------------- */ -double H5F_rdcc_w0(const H5F_t *f) +double +H5F_rdcc_w0(const H5F_t *f) { /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_w0) @@ -3995,7 +2943,8 @@ double H5F_rdcc_w0(const H5F_t *f) * *------------------------------------------------------------------------- */ -hbool_t H5F_has_feature(const H5F_t *f, unsigned feature) +hbool_t +H5F_has_feature(const H5F_t *f, unsigned feature) { /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_has_feature) @@ -4272,7 +3221,8 @@ done: * *------------------------------------------------------------------------- */ -H5RC_t *H5F_grp_btree_shared(const H5F_t *f) +H5RC_t * +H5F_grp_btree_shared(const H5F_t *f) { /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_grp_btree_shared) diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 642b9d9..1c91b8e 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -158,7 +158,21 @@ union H5D_storage_t; #ifdef NOT_YET H5_DLL void H5F_encode_length_unusual(const H5F_t *f, uint8_t **p, uint8_t *l); #endif /* NOT_YET */ + +/* General routines */ +H5_DLL herr_t H5F_close(H5F_t *f); +H5_DLL haddr_t H5F_locate_signature(H5FD_t *file, hid_t dxpl_id); + +/* File mount related routines */ H5_DLL herr_t H5F_mountpoint(struct H5G_entry_t *find/*in,out*/); +H5_DLL herr_t H5F_close_mounts(H5F_t *f); +H5_DLL int H5F_term_unmount_cb(void *obj_ptr, hid_t obj_id, void *key); +H5_DLL herr_t H5F_check_mounts(H5F_t *f); + +/* Superblock related routines */ +H5_DLL herr_t H5F_init_superblock(const H5F_t *f, hid_t dxpl_id); +H5_DLL herr_t H5F_write_superblock(H5F_t *f, hid_t dxpl_id); +H5_DLL herr_t H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent); #endif diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index 4cb1646..b4a57ef 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -67,16 +67,11 @@ H5F_init_super_interface(void) * Sept 12, 2003 * * Modifications: - * Raymond Lu - * May 24, 2005 - * Started to check if driver(only family and multi drivers) - * matches driver information saved in the superblock. Wrong - * driver will result in a failure. - * + * *------------------------------------------------------------------------- */ herr_t -H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr, uint8_t *buf, size_t buf_size) +H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent) { haddr_t stored_eoa; /*relative end-of-addr in file */ haddr_t eof; /*end of file address */ @@ -90,7 +85,6 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr H5F_file_t *shared = NULL; /* shared part of `file' */ H5FD_t *lf = NULL; /* file driver part of `shared' */ uint8_t *p; /* Temporary pointer into encoding buffers */ - uint8_t *start_p; /* Start of encoding buffers */ unsigned i; /* Index variable */ unsigned chksum; /* Checksum temporary variable */ size_t driver_size; /* Size of driver info block, in bytes */ @@ -99,7 +93,7 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr unsigned freespace_vers; /* Freespace info version */ unsigned obj_dir_vers; /* Object header info version */ unsigned share_head_vers; /* Shared header info version */ - uint8_t sbuf[H5F_SUPERBLOCK_SIZE]; /* Local buffer */ + uint8_t buf[H5F_SUPERBLOCK_SIZE]; /* Local buffer */ H5P_genplist_t *c_plist; /* File creation property list */ herr_t ret_value = SUCCEED; @@ -115,26 +109,14 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") /* Read the superblock if it hasn't been read before. */ - if (addr == HADDR_UNDEF) { - if (HADDR_UNDEF == (shared->super_addr=H5F_locate_signature(lf,dxpl_id))) - HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to find file signature") - } else { - shared->super_addr = addr; - } - - if (!buf) { - start_p = p = sbuf; - buf_size=sizeof(sbuf); - - if (H5FD_set_eoa(lf, shared->super_addr + fixed_size) < 0 || - H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr, fixed_size, p) < 0) - HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "unable to read superblock") - } else { - start_p = p = buf; - } + if (HADDR_UNDEF == (shared->super_addr=H5F_locate_signature(lf,dxpl_id))) + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to find file signature") + if (H5FD_set_eoa(lf, shared->super_addr + fixed_size) < 0 || + H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr, fixed_size, buf) < 0) + HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "unable to read superblock") /* Signature, already checked */ - p += H5F_SIGNATURE_LEN; + p = buf + H5F_SIGNATURE_LEN; /* Superblock version */ super_vers = *p++; @@ -209,7 +191,7 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr /* File consistency flags. Not really used yet */ UINT32DECODE(p, shared->consist_flags); - assert(((size_t)(p - start_p)) == fixed_size); + assert(((size_t)(p - buf)) == fixed_size); /* Decode the variable-length part of the superblock... */ variable_size = (super_vers>0 ? 4 : 0) + /* Potential indexed storage B-tree internal 'K' value */ @@ -218,15 +200,10 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr H5F_SIZEOF_ADDR(f) + /*end-of-address*/ H5F_SIZEOF_ADDR(f) + /*reserved address*/ H5G_SIZEOF_ENTRY(f); /*root group ptr*/ - assert(fixed_size + variable_size <= buf_size); - - /* The buffer (buf) is either passed in or the "local_buf" variable now */ - if(!buf) { - if (H5FD_set_eoa(lf, shared->super_addr + fixed_size+variable_size) < 0 || - H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr + fixed_size, - variable_size, p) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read superblock") - } /* end if */ + assert(fixed_size + variable_size <= sizeof(buf)); + if (H5FD_set_eoa(lf, shared->super_addr + fixed_size+variable_size) < 0 || + H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr + fixed_size, variable_size, p) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read superblock") /* * If the superblock version # is greater than 0, read in the indexed @@ -269,37 +246,20 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr /* Compute super block checksum */ assert(sizeof(chksum) == sizeof(shared->super_chksum)); for (q = (uint8_t *)&chksum, chksum = 0, i = 0; i < fixed_size + variable_size; ++i) - q[i % sizeof(shared->super_chksum)] ^= start_p[i]; + q[i % sizeof(shared->super_chksum)] ^= buf[i]; /* Set the super block checksum */ shared->super_chksum = chksum; - /* This step is for h5repart tool only. If user wants to change file driver from - * family to sec2 while using h5repart, set the driver address to undefined to let - * the library ignore the family driver information saved in the superblock. - */ - if(shared->fam_to_sec2) - shared->driver_addr = HADDR_UNDEF; - /* Decode the optional driver information block */ if (H5F_addr_defined(shared->driver_addr)) { haddr_t drv_addr = shared->base_addr + shared->driver_addr; uint8_t dbuf[H5F_DRVINFOBLOCK_SIZE]; /* Local buffer */ - size_t dbuf_size; /* Size available for driver info */ - const uint8_t *driver_p; /* Remember beginning of driver info block */ - if(!buf) { - driver_p = p = dbuf; - dbuf_size=sizeof(dbuf); - - if (H5FD_set_eoa(lf, drv_addr + 16) < 0 || - H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr, (size_t)16, p) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read driver information block") - } /* end if */ - else { - driver_p = p; - dbuf_size=buf_size-(p-start_p); - } /* end else */ + if (H5FD_set_eoa(lf, drv_addr + 16) < 0 || + H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr, (size_t)16, dbuf) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read driver information block") + p = dbuf; /* Version number */ if (HDF5_DRIVERINFO_VERSION != *p++) @@ -316,28 +276,18 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr p += 8; /* advance past name/version */ /* Read driver information and decode */ - assert((driver_size + 16) <= dbuf_size); + assert((driver_size + 16) <= sizeof(dbuf)); + if (H5FD_set_eoa(lf, drv_addr + 16 + driver_size) < 0 || + H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr+16, driver_size, p) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read file driver information") - if(!buf) { - if (H5FD_set_eoa(lf, drv_addr + 16 + driver_size) < 0 || - H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr+16, driver_size, p) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read file driver information") - } /* end if */ - - /* Check if driver matches driver information saved. Unfortunately, we can't push this - * function to each specific driver because we're checking if the driver is correct.*/ - if(!HDstrncmp(driver_name, "NCSAfami", 8) && HDstrcmp(lf->cls->name, "family")) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "family driver should be used") - if(!HDstrncmp(driver_name, "NCSAmult", 8) && HDstrcmp(lf->cls->name, "multi")) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "multi driver should be used") - if (H5FD_sb_decode(lf, driver_name, p) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to decode driver information") /* Compute driver info block checksum */ assert(sizeof(chksum) == sizeof(shared->drvr_chksum)); for (q = (uint8_t *)&chksum, chksum = 0, i = 0; i < (driver_size + 16); ++i) - q[i % sizeof(shared->drvr_chksum)] ^= driver_p[i]; + q[i % sizeof(shared->drvr_chksum)] ^= dbuf[i]; /* Set the driver info block checksum */ shared->drvr_chksum = chksum; @@ -357,12 +307,8 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr */ if (HADDR_UNDEF == (eof = H5FD_get_eof(lf))) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size") - -#ifdef H5_HAVE_FPHDF5 - if (!H5FD_is_fphdf5_driver(lf) || H5FD_fphdf5_is_captain(lf)) -#endif /* !H5_HAVE_FPHDF5 */ - if (eof < stored_eoa) - HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, FAIL, "truncated file") + if (eof < stored_eoa) + HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, FAIL, "truncated file") /* * Tell the file driver how much address space has already been @@ -394,7 +340,7 @@ done: * *------------------------------------------------------------------------- */ -hsize_t +herr_t H5F_init_superblock(const H5F_t *f, hid_t dxpl_id) { hsize_t userblock_size = 0; /* Size of userblock, in bytes */ @@ -403,14 +349,14 @@ H5F_init_superblock(const H5F_t *f, hid_t dxpl_id) unsigned super_vers; /* Super block version */ haddr_t addr; /* Address of superblock */ H5P_genplist_t *plist; /* Property list */ - hsize_t ret_value; + herr_t ret_value=SUCCEED; /* Encoding */ - FUNC_ENTER_NOAPI(H5F_init_superblock, UFAIL) + FUNC_ENTER_NOAPI(H5F_init_superblock, FAIL) /* Get the shared file creation property list */ if (NULL == (plist = H5I_object(f->shared->fcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, UFAIL, "not a property list") + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") /* * The superblock starts immediately after the user-defined @@ -419,14 +365,14 @@ H5F_init_superblock(const H5F_t *f, hid_t dxpl_id) * now. */ if(H5P_get(plist, H5F_CRT_USER_BLOCK_NAME, &userblock_size) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, UFAIL, "unable to get user block size") + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get user block size") f->shared->super_addr = userblock_size; f->shared->base_addr = f->shared->super_addr; f->shared->consist_flags = 0x03; /* Grab superblock version from property list */ if (H5P_get(plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, UFAIL, "unable to get super block version") + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get super block version") /* Compute the size of the superblock */ superblock_size=H5F_SIGNATURE_LEN /* Signature length (8 bytes) */ @@ -453,11 +399,11 @@ H5F_init_superblock(const H5F_t *f, hid_t dxpl_id) ((hsize_t)f->shared->base_addr + superblock_size + driver_size)); if (HADDR_UNDEF == addr) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, UFAIL, + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to allocate file space for userblock and/or superblock") if (0 != addr) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, UFAIL, + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "file driver failed to allocate userblock and/or superblock at address zero") /* @@ -467,9 +413,6 @@ H5F_init_superblock(const H5F_t *f, hid_t dxpl_id) if (driver_size > 0) f->shared->driver_addr = superblock_size; - /* Return the size of the super block+driver info block */ - ret_value=superblock_size+driver_size; - done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_init_superblock() */ @@ -495,7 +438,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5F_write_superblock(H5F_t *f, hid_t dxpl_id, uint8_t *buf) +H5F_write_superblock(H5F_t *f, hid_t dxpl_id) { uint8_t sbuf[H5F_SUPERBLOCK_SIZE]; /* Superblock encoding buffer */ uint8_t dbuf[H5F_DRVINFOBLOCK_SIZE];/* Driver info block encoding buffer*/ @@ -634,12 +577,6 @@ H5F_write_superblock(H5F_t *f, hid_t dxpl_id, uint8_t *buf) } /* end if */ } /* end if */ - /* Update the user's buffer, if given */ - if (buf) { - HDmemcpy(buf, sbuf, superblock_size); - HDmemcpy(&buf[superblock_size], dbuf, driver_size); - } /* end if */ - done: FUNC_LEAVE_NOAPI(ret_value) } @@ -1406,7 +1406,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, +H5G_namei(const H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/, unsigned target, int *nlinks/*out*/, H5G_namei_act_t action, H5G_entry_t *ent, hid_t dxpl_id) @@ -1559,7 +1559,7 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, if(H5G_CACHED_SLINK==obj_ent->type && (0==(target & H5G_TARGET_SLINK) || !last_comp)) { if ((*nlinks)-- <= 0) - HGOTO_ERROR (H5E_SYM, H5E_SLINK, FAIL, "too many symbolic links"); + HGOTO_ERROR (H5E_SYM, H5E_SLINK, FAIL, "too many links"); if (H5G_traverse_slink (grp_ent, obj_ent, nlinks, dxpl_id)<0) HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "symbolic link traversal failed"); } @@ -1633,7 +1633,7 @@ H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/, const H5HL_t *heap; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5G_traverse_slink, FAIL); + FUNC_ENTER_NOAPI_NOINIT(H5G_traverse_slink); /* Portably initialize the temporary group entry */ HDmemset(&tmp_grp_ent,0,sizeof(H5G_entry_t)); @@ -2158,6 +2158,11 @@ H5G_close(H5G_t *grp) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close"); H5FL_FREE (H5G_shared_t, grp->shared); } else { + /* Check if this group was the last object holding open a mounted file + * hierarchy and close down the file hierarchy if so */ + if(grp->shared->fo_count == 1) + H5F_check_mounts(grp->ent.file); + if(H5G_free_ent_name(&(grp->ent))<0) { H5FL_FREE (H5G_t,grp); @@ -3974,3 +3979,29 @@ done: FUNC_LEAVE_NOAPI(ret_value); } + +/*------------------------------------------------------------------------- + * Function: H5G_get_shared_count + * + * Purpose: Queries the group object's "shared count" + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, July 5, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_get_shared_count(H5G_t *grp) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_get_shared_count); + + /* Check args */ + assert(grp && grp->shared); + + FUNC_LEAVE_NOAPI(grp->shared->fo_count); +} /* end H5G_get_shared_count() */ + diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 9c098ba..26a7e78 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -156,6 +156,7 @@ H5_DLL herr_t H5G_replace_name(int type, H5G_entry_t *loc, H5RS_str_t *src_name, H5G_entry_t *src_loc, H5RS_str_t *dst_name, H5G_entry_t *dst_loc, H5G_names_op_t op); H5_DLL herr_t H5G_free_grp_name(H5G_t *grp); +H5_DLL herr_t H5G_get_shared_count(H5G_t *grp); /* * These functions operate on symbol table nodes. @@ -3679,7 +3679,7 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset) /* Compare the members */ base_size = dt1->shared->parent->shared->size; for (u=0; u<dt1->shared->u.enumer.nmembs; u++) { - unsigned idx; + unsigned idx = 0; if(superset) { unsigned lt = 0, rt; /* Final, left & right key indices */ diff --git a/src/Makefile.in b/src/Makefile.in index 3120e88..3f41853 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -32,7 +32,7 @@ DISTCLEAN=libhdf5.settings ## Source and object files for the library (lexicographically)... LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5C.c H5D.c H5Dcontig.c H5Dcompact.c H5Defl.c \ H5Dio.c H5Distore.c H5Dmpio.c H5Dselect.c H5Dtest.c H5E.c H5F.c \ - H5Fdbg.c H5FD.c \ + H5Fdbg.c H5Fmount.c H5Fsuper.c H5FD.c \ H5FDcore.c H5FDfamily.c H5FDgass.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDsrb.c H5FDstdio.c \ H5FDstream.c H5FL.c H5FO.c H5FS.c H5G.c H5Gent.c H5Gnode.c H5Gstab.c \ diff --git a/test/mount.c b/test/mount.c index ce35830..d4fc819 100644 --- a/test/mount.c +++ b/test/mount.c @@ -19,6 +19,7 @@ * Purpose: Tests file mounting. */ #include "h5test.h" +#include "H5Iprivate.h" /* IDs */ const char *FILENAME[] = { "mount_1", @@ -1653,7 +1654,15 @@ test_missing_unmount(hid_t fapl) /* Close group in top file */ if(H5Gclose(gidA) < 0) TEST_ERROR - + + /* Check that all file IDs have been closed */ + if(H5I_nmembers(H5I_FILE) != 0) + TEST_ERROR + + /* Check that all "file closing" IDs have been closed */ + if(H5I_nmembers(H5I_FILE_CLOSING) != 0) + TEST_ERROR + PASSED(); return 0; @@ -1673,6 +1682,133 @@ error: /*------------------------------------------------------------------------- + * Function: test_hold_open + * + * Purpose: Test that the library correctly holds open files when they + * have child files that have not been unmounted. + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Tuesday, July 5, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_hold_open(hid_t fapl) +{ + hid_t fid1 = -1, fid2 = -1; /* File IDs */ + hid_t gidA = -1, gidM = -1, gidAM = -1; /* Group IDs */ + char filename1[1024], + filename2[1024]; /* Name of files to mount */ + + TESTING("hold open"); + + h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2); + + /* Create file #1 */ + if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidA) < 0) + TEST_ERROR + + if(H5Fclose(fid1) < 0) + TEST_ERROR + + + /* Create file #2 */ + if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidM = H5Gcreate(fid2, "M", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidM) < 0) + TEST_ERROR + + if(H5Fclose(fid2) < 0) + TEST_ERROR + + + /* Re-open files and mount file #2 in file #1 */ + if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidA = H5Gopen(fid1, "A")) < 0) + TEST_ERROR + + if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + + if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0) + TEST_ERROR + + if((gidAM = H5Gopen(fid1, "A/M")) < 0) + TEST_ERROR + + /* Close file #2 */ + if(H5Fclose(fid2) < 0) + TEST_ERROR + + /* Close group in mounted file */ + if(H5Gclose(gidAM) < 0) + TEST_ERROR + + /* Attempt to open group in mounted file */ + /* (Should work because file is still mounted) */ + if((gidAM = H5Gopen(fid1, "A/M")) < 0) + TEST_ERROR + + /* Close file #1 */ + if(H5Fclose(fid1) < 0) + TEST_ERROR + + /* Close group in mounted file */ + if(H5Gclose(gidAM) < 0) + TEST_ERROR + + /* Attempt to open group in mounted file */ + /* (Should work because file is still mounted) */ + if((gidAM = H5Gopen(gidA, "/A/M")) < 0) + TEST_ERROR + + /* Close group in mounted file */ + if(H5Gclose(gidAM) < 0) + TEST_ERROR + + /* Unmount file #2 */ + if(H5Funmount(gidA, ".") < 0) + TEST_ERROR + + /* Close group in top file */ + if(H5Gclose(gidA) < 0) + TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gidM); + H5Gclose(gidAM); + H5Gclose(gidA); + H5Fclose(fid2); + H5Fclose(fid1); + } H5E_END_TRY; + return 1; +} /* end test_hold_open() */ + + +/*------------------------------------------------------------------------- * Function: main * * Purpose: Test file mounting @@ -1714,6 +1850,7 @@ main(void) nerrors += test_mount_after_close(fapl); nerrors += test_mount_after_unmount(fapl); nerrors += test_missing_unmount(fapl); + nerrors += test_hold_open(fapl); if (nerrors) goto error; puts("All mount tests passed."); |