From 502b4c206d238dff6bdca09075ffeb426a365a9e Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Mon, 8 Aug 2005 13:41:35 -0500 Subject: [svn-r11215] Purpose: Bug fix & code cleanup Description: Fix another bug in the file mounting code and refactor the unmount code that it is simpler. Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4 Too minor to require h5committest --- MANIFEST | 1 + src/H5F.c | 212 +------- src/H5Fmount.c | 89 ++-- src/H5Fpkg.h | 5 + src/H5Fprivate.h | 3 + src/H5Fsfile.c | 226 ++++++++ src/Makefile.am | 2 +- src/Makefile.in | 42 +- test/mount.c | 1203 ++++++++++++++++++++++++++++++++++++++++++ test/tfile.c | 4 + tools/h5diff/h5diff_common.c | 2 +- tools/lib/h5diff.h | 2 +- 12 files changed, 1537 insertions(+), 254 deletions(-) create mode 100644 src/H5Fsfile.c diff --git a/MANIFEST b/MANIFEST index 1201958..0d8bd06 100644 --- a/MANIFEST +++ b/MANIFEST @@ -429,6 +429,7 @@ a------------------------------------------------------------------------------ ./src/H5F.c ./src/H5Fdbg.c ./src/H5Fmount.c +./src/H5Fsfile.c ./src/H5Fsuper.c ./src/H5Fpkg.h ./src/H5Fprivate.h diff --git a/src/H5F.c b/src/H5F.c index ea9e608..4cd5b67 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -60,12 +60,6 @@ typedef struct H5F_olist_t { int max_index; /* Maximum # of IDs to put into array */ } H5F_olist_t; -/* Struct for tracking "shared" file structs */ -typedef struct H5F_sfile_node_t { - H5F_file_t *shared; /* Pointer to "shared" struct */ - struct H5F_sfile_node_t *next; /* Pointer to next node */ -} H5F_sfile_node_t; - /* PRIVATE PROTOTYPES */ #ifdef NOT_YET @@ -81,23 +75,12 @@ static unsigned H5F_get_objects(const H5F_t *f, unsigned types, int max_objs, hi 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); -/* Routines to operate on the shared file list */ -static herr_t H5F_shared_add(H5F_file_t *shared); -static H5F_file_t * H5F_shared_search(H5FD_t *lf); -static herr_t H5F_shared_remove(H5F_file_t *shared); - /* Declare a free list to manage the H5F_t struct */ H5FL_DEFINE_STATIC(H5F_t); /* Declare a free list to manage the H5F_file_t struct */ H5FL_DEFINE_STATIC(H5F_file_t); -/* Declare a free list to manage the H5F_sfile_node_t struct */ -H5FL_DEFINE_STATIC(H5F_sfile_node_t); - -/* Declare a local variable to track the shared file information */ -H5F_sfile_node_t *H5F_sfile_head_g = NULL; - /*------------------------------------------------------------------------- * Function: H5F_init @@ -452,7 +435,7 @@ H5F_term_interface(void) H5I_clear_type(H5I_FILE, FALSE); } else { /* Make certain we've cleaned up all the shared file objects */ - HDassert(H5F_sfile_head_g == NULL); + H5F_sfile_assert_num(0); H5I_dec_type_ref(H5I_FILE); H5_interface_initialize_g = 0; @@ -1535,7 +1518,7 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure") /* Add new "shared" struct to list of open files */ - if(H5F_shared_add(f->shared) < 0) + if(H5F_sfile_add(f->shared) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to append to list of open files") } /* end else */ @@ -1601,7 +1584,7 @@ H5F_dest(H5F_t *f, hid_t dxpl_id) if (1==f->shared->nrefs) { /* Remove shared file struct from list of open files */ - if(H5F_shared_remove(f->shared) < 0) { + if(H5F_sfile_remove(f->shared) < 0) { HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file"); ret_value = FAIL; /*but keep going*/ } /* end if */ @@ -1811,7 +1794,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d } /* end if */ /* Is the file already open? */ - if ((shared = H5F_shared_search(lf)) != NULL) { + if ((shared = H5F_sfile_search(lf)) != NULL) { /* * The file is already open, so use that one instead of the one we * just opened. We only one one H5FD_t* per file so one doesn't @@ -2579,6 +2562,24 @@ H5F_close(H5F_t *f) HDassert(f); HDassert(f->file_id > 0); /* This routine should only be called when a file ID's ref count drops to zero */ + /* Perform checks for "semi" file close degree here, since closing the + * file is not allowed if there are objects still open */ + if(f->shared->fc_degree == H5F_CLOSE_SEMI) { + unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */ + unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */ + + /* Get the number of open objects and open files on this file/mount hierarchy */ + if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0) + HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy") + + /* If there are no other file IDs open on this file/mount hier., but + * there are still open objects, issue an error and bail out now, + * without decrementing the file ID's reference count and triggering + * a "real" attempt at closing the file */ + if(nopen_files == 1 && nopen_objs > 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open") + } /* end if */ + /* Reset the file ID for this file */ f->file_id = -1; @@ -2781,43 +2782,15 @@ done: herr_t H5Fclose(hid_t file_id) { - H5F_t *f; herr_t ret_value = SUCCEED; FUNC_ENTER_API(H5Fclose, FAIL) H5TRACE1("e","i",file_id); /* Check/fix arguments. */ - if (NULL == (f = H5I_object_verify(file_id,H5I_FILE))) + if (H5I_FILE != H5I_get_type(file_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file ID") - /* Perform checks for "semi" file close degree here, since closing the - * file ID will mess things up if we need to return FAIL */ - if(f->shared->fc_degree == H5F_CLOSE_SEMI) { - int ref_count; /* Reference count for file's ID */ - - /* Get the reference count for this ID */ - if((ref_count = H5I_get_ref(file_id)) < 0) - HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID ref count") - - /* If we will be decrementing the reference count to zero, check for objects open */ - if(ref_count == 1) { - unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */ - unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */ - - /* Get the number of open objects and open files on this file/mount hierarchy */ - if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0) - HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy") - - /* If there are no other file IDs open on this file/mount hier., but - * there are still open objects, issue an error and bail out now, - * before decrementing the file ID's reference count and triggering - * a "real" attempt at closing the file */ - if(nopen_files == 1 && nopen_objs > 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open") - } /* end if */ - } /* end if */ - /* * Decrement reference count on atom. When it reaches zero the file will * be closed. @@ -4163,142 +4136,3 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Fget_name() */ - -/*------------------------------------------------------------------------- - * Function: H5F_shared_add - * - * Purpose: Add a "shared" file struct to the list of open files - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * Monday, July 18, 2005 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5F_shared_add(H5F_file_t *shared) -{ - H5F_sfile_node_t *new_shared; /* New shared file node */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5F_shared_add) - - /* Sanity check */ - HDassert(shared); - - /* Allocate new shared file node */ - if (NULL == (new_shared = H5FL_CALLOC(H5F_sfile_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - - /* Set shared file value */ - new_shared->shared = shared; - - /* Prepend to list of shared files open */ - new_shared->next = H5F_sfile_head_g; - H5F_sfile_head_g = new_shared; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_shared_add() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_shared_search - * - * Purpose: Search for a "shared" file with low-level file info that - * matches - * - * Return: Non-NULL on success / NULL on failure - * - * Programmer: Quincey Koziol - * Monday, July 18, 2005 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static H5F_file_t * -H5F_shared_search(H5FD_t *lf) -{ - H5F_sfile_node_t *curr; /* Current shared file node */ - H5F_file_t *ret_value = NULL; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_shared_search) - - /* Sanity check */ - HDassert(lf); - - /* Iterate through low-level files for matching low-level file info */ - curr = H5F_sfile_head_g; - while(curr) { - /* Check for match */ - if(0==H5FD_cmp(curr->shared->lf, lf)) - HGOTO_DONE(curr->shared) - - /* Advance to next shared file node */ - curr = curr->next; - } /* end while */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_shared_search() */ - - -/*------------------------------------------------------------------------- - * Function: H5F_shared_remove - * - * Purpose: Remove a "shared" file struct from the list of open files - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * Monday, July 18, 2005 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5F_shared_remove(H5F_file_t *shared) -{ - H5F_sfile_node_t *curr; /* Current shared file node */ - H5F_sfile_node_t *last; /* Last shared file node */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5F_shared_remove) - - /* Sanity check */ - HDassert(shared); - - /* Locate shared file node with correct shared file */ - last = NULL; - curr = H5F_sfile_head_g; - while(curr && curr->shared != shared) { - /* Advance to next node */ - last = curr; - curr = curr->next; - } /* end while */ - - /* Indicate error if the node wasn't found */ - if(curr == NULL) - HGOTO_ERROR(H5E_FILE, H5E_NOTFOUND, FAIL, "can't find shared file info") - - /* Remove node found from list */ - if(last != NULL) - /* Removing middle or tail node in list */ - last->next = curr->next; - else - /* Removing head node in list */ - H5F_sfile_head_g = curr->next; - - /* Release the shared file node struct */ - /* (the shared file info itself is freed elsewhere) */ - H5FL_FREE(H5F_sfile_node_t, curr); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_shared_remove() */ - diff --git a/src/H5Fmount.c b/src/H5Fmount.c index 7e234a5..18feb9c 100644 --- a/src/H5Fmount.c +++ b/src/H5Fmount.c @@ -34,7 +34,7 @@ NAME H5F_init_mount_interface -- Initialize interface-specific information USAGE - herr_t H5T_init_mount_interface() + herr_t H5F_init_mount_interface() RETURNS Non-negative on success/Negative on failure @@ -256,15 +256,15 @@ static herr_t H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id) { H5G_t *mounted = NULL; /*mount point group */ + H5G_t *child_group = NULL; /* Child's group in parent mtab */ + H5F_t *child_file = NULL; /* Child's file in parent mtab */ 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*/ + H5G_entry_t mnt_open_ent; /* entry used to open mount point*/ + int child_idx; /* Index of child in parent's mtab */ + herr_t ret_value = SUCCEED; /*return value */ FUNC_ENTER_NOAPI_NOINIT(H5F_unmount) @@ -283,37 +283,27 @@ H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id) child = H5G_fileof(mounted); mnt_ent = H5G_entof(mounted); ent = H5G_entof(child->shared->root_grp); + child_idx = -1; if (child->mtab.parent && H5F_addr_eq(mnt_ent->header, ent->header)) { + unsigned u; /*counters */ + /* * 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; imtab.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_unmount(parent->mtab.child[md].group)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to reset group mounted flag") - 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_try_close(child)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file") - - /* Eliminate the mount point from the table */ - HDmemmove(parent->mtab.child+i, parent->mtab.child+i+1, - (parent->mtab.nmounts-i)* sizeof(parent->mtab.child[0])); - ret_value = SUCCEED; + for (u=0; umtab.nmounts; u++) { + if (parent->mtab.child[u].file==child) { + /* Found the correct index */ + child_idx = u; + break; } } - HDassert(ret_value>=0); } else { + unsigned lt, rt, md=0; /*binary search indices */ + int cmp; /*binary search comparison value*/ + /* * 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. @@ -335,22 +325,37 @@ H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id) if (cmp) HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "not a mount point") - /* Unmount the child */ - parent->mtab.nmounts -= 1; - if(H5G_unmount(parent->mtab.child[md].group)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to reset group mounted flag") - 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_try_close(parent->mtab.child[md].file)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file") - - /* Eliminate the mount point from the table */ - HDmemmove(parent->mtab.child+md, parent->mtab.child+md+1, - (parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0])); - ret_value = SUCCEED; + /* Found the correct index */ + child_idx = md; + mnt_ent = ent; } - + + HDassert(child_idx >= 0); + + /* 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 ") + + /* Save the information about the child from the mount table */ + child_group = parent->mtab.child[child_idx].group; + child_file = parent->mtab.child[child_idx].file; + + /* Eliminate the mount point from the table */ + HDmemmove(parent->mtab.child+child_idx, parent->mtab.child+child_idx+1, + (parent->mtab.nmounts-child_idx)*sizeof(parent->mtab.child[0])); + parent->mtab.nmounts -= 1; + + /* Unmount the child file from the parent file */ + if(H5G_unmount(child_group)<0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to reset group mounted flag") + if(H5G_close(child_group)<0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group") + + /* Detach child file from parent & see if it should close */ + child_file->mtab.parent = NULL; + if(H5F_try_close(child_file)<0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file") + done: if (mounted) if(H5G_close(mounted)<0 && ret_value>=0) diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 596103e..8e68d0b 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -178,5 +178,10 @@ H5_DLL hsize_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, uint8_t *buf); H5_DLL 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); +/* Shared file list related routines */ +H5_DLL herr_t H5F_sfile_add(H5F_file_t *shared); +H5_DLL H5F_file_t * H5F_sfile_search(H5FD_t *lf); +H5_DLL herr_t H5F_sfile_remove(H5F_file_t *shared); + #endif diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 52b92dc..697a260 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -481,6 +481,9 @@ H5_DLL herr_t H5F_acs_close(hid_t fapl_id, void *close_data); H5_DLL herr_t H5F_acs_copy(hid_t new_fapl_id, hid_t old_fapl_id, void *close_data); +/* Shared file list related routines */ +H5_DLL herr_t H5F_sfile_assert_num(unsigned n); + /* Debugging functions */ H5_DLL herr_t H5F_debug(H5F_t *f, hid_t dxpl_id, FILE * stream, int indent, int fwidth); diff --git a/src/H5Fsfile.c b/src/H5Fsfile.c new file mode 100644 index 0000000..70eb420 --- /dev/null +++ b/src/H5Fsfile.c @@ -0,0 +1,226 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ + +/* Packages needed by this file... */ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5FDprivate.h" /* File drivers */ +#include "H5FLprivate.h" /* Free lists */ + +/* PRIVATE TYPEDEFS */ + +/* Struct for tracking "shared" file structs */ +typedef struct H5F_sfile_node_t { + H5F_file_t *shared; /* Pointer to "shared" file struct */ + struct H5F_sfile_node_t *next; /* Pointer to next node */ +} H5F_sfile_node_t; + +/* PRIVATE PROTOTYPES */ + +/* PRIVATE VARIABLES */ + +/* Declare a free list to manage the H5F_sfile_node_t struct */ +H5FL_DEFINE_STATIC(H5F_sfile_node_t); + +/* Declare a local variable to track the shared file information */ +H5F_sfile_node_t *H5F_sfile_head_g = NULL; + + +/*------------------------------------------------------------------------- + * Function: H5F_sfile_assert_empty + * + * Purpose: Sanity checking that shared file list is empty + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * Monday, July 25, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_sfile_assert_num(unsigned n) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sfile_assert_num) + + if(n == 0) { + /* Sanity checking */ + HDassert(H5F_sfile_head_g == NULL); + } /* end if */ + else { + unsigned count; /* Number of open shared files */ + H5F_sfile_node_t *curr; /* Current shared file node */ + + /* Iterate through low-level files for matching low-level file info */ + curr = H5F_sfile_head_g; + count = 0; + while(curr) { + /* Increment # of open shared file structs */ + count++; + + /* Advance to next shared file node */ + curr = curr->next; + } /* end while */ + + /* Sanity checking */ + HDassert(count == n); + } /* end else */ + + FUNC_LEAVE_NOAPI(SUCCEED); +} /* H5F_sfile_assert_num() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_sfile_add + * + * Purpose: Add a "shared" file struct to the list of open files + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * Monday, July 18, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_sfile_add(H5F_file_t *shared) +{ + H5F_sfile_node_t *new_shared; /* New shared file node */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5F_sfile_add) + + /* Sanity check */ + HDassert(shared); + + /* Allocate new shared file node */ + if (NULL == (new_shared = H5FL_CALLOC(H5F_sfile_node_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Set shared file value */ + new_shared->shared = shared; + + /* Prepend to list of shared files open */ + new_shared->next = H5F_sfile_head_g; + H5F_sfile_head_g = new_shared; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_sfile_add() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_sfile_search + * + * Purpose: Search for a "shared" file with low-level file info that + * matches + * + * Return: Non-NULL on success / NULL on failure + * + * Programmer: Quincey Koziol + * Monday, July 18, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5F_file_t * +H5F_sfile_search(H5FD_t *lf) +{ + H5F_sfile_node_t *curr; /* Current shared file node */ + H5F_file_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sfile_search) + + /* Sanity check */ + HDassert(lf); + + /* Iterate through low-level files for matching low-level file info */ + curr = H5F_sfile_head_g; + while(curr) { + /* Check for match */ + if(0==H5FD_cmp(curr->shared->lf, lf)) + HGOTO_DONE(curr->shared) + + /* Advance to next shared file node */ + curr = curr->next; + } /* end while */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_sfile_search() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_sfile_remove + * + * Purpose: Remove a "shared" file struct from the list of open files + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * Monday, July 18, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_sfile_remove(H5F_file_t *shared) +{ + H5F_sfile_node_t *curr; /* Current shared file node */ + H5F_sfile_node_t *last; /* Last shared file node */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5F_sfile_remove) + + /* Sanity check */ + HDassert(shared); + + /* Locate shared file node with correct shared file */ + last = NULL; + curr = H5F_sfile_head_g; + while(curr && curr->shared != shared) { + /* Advance to next node */ + last = curr; + curr = curr->next; + } /* end while */ + + /* Indicate error if the node wasn't found */ + if(curr == NULL) + HGOTO_ERROR(H5E_FILE, H5E_NOTFOUND, FAIL, "can't find shared file info") + + /* Remove node found from list */ + if(last != NULL) + /* Removing middle or tail node in list */ + last->next = curr->next; + else + /* Removing head node in list */ + H5F_sfile_head_g = curr->next; + + /* Release the shared file node struct */ + /* (the shared file info itself is freed elsewhere) */ + H5FL_FREE(H5F_sfile_node_t, curr); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_sfile_remove() */ + diff --git a/src/Makefile.am b/src/Makefile.am index 0644418..7091120 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -48,7 +48,7 @@ libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2cache.c H5B2dbg.c \ H5Dcontig.c \ H5Dcompact.c \ H5Defl.c H5Dio.c H5Distore.c H5Dmpio.c H5Dselect.c H5Dtest.c H5E.c H5F.c \ - H5Fdbg.c H5Fmount.c H5Fsuper.c H5FD.c H5FDcore.c \ + H5Fdbg.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5FD.c H5FDcore.c \ H5FDfamily.c H5FDfphdf5.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \ H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c \ diff --git a/src/Makefile.in b/src/Makefile.in index c92dabe..109c53f 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -88,25 +88,26 @@ am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5B2.lo \ H5BTdbg.lo H5BTtest.lo H5C.lo H5D.lo H5Dcontig.lo \ H5Dcompact.lo H5Defl.lo H5Dio.lo H5Distore.lo H5Dmpio.lo \ H5Dselect.lo H5Dtest.lo H5E.lo H5F.lo H5Fdbg.lo H5Fmount.lo \ - H5Fsuper.lo H5FD.lo H5FDcore.lo H5FDfamily.lo H5FDfphdf5.lo \ - H5FDlog.lo H5FDmpi.lo H5FDmpio.lo H5FDmpiposix.lo H5FDmulti.lo \ - H5FDsec2.lo H5FDstdio.lo H5FDstream.lo H5FL.lo H5FO.lo H5FP.lo \ - H5FPclient.lo H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo \ - H5Gnode.lo H5Gstab.lo H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo \ - H5HP.lo H5I.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \ - H5Oattr.lo H5Obogus.lo H5Ocont.lo H5Odtype.lo H5Oefl.lo \ - H5Ofill.lo H5Olayout.lo H5Omtime.lo H5Oname.lo H5Onull.lo \ - H5Opline.lo H5Osdspace.lo H5Oshared.lo H5Ostab.lo H5P.lo \ - H5Pdcpl.lo H5Pdxpl.lo H5Pfapl.lo H5Pfcpl.lo H5Pocpl.lo \ - H5Ptest.lo H5R.lo H5RC.lo H5RS.lo H5S.lo H5Sall.lo H5Shyper.lo \ - H5Smpio.lo H5Snone.lo H5Spoint.lo H5Sselect.lo H5Stest.lo \ - H5SH.lo H5SHcache.lo H5SHdbg.lo H5SL.lo H5ST.lo H5T.lo \ - H5Tarray.lo H5Tbit.lo H5Tcommit.lo H5Tcompound.lo H5Tconv.lo \ - H5Tcset.lo H5Tenum.lo H5Tfields.lo H5Tfixed.lo H5Tfloat.lo \ - H5Tinit.lo H5Tnative.lo H5Toffset.lo H5Topaque.lo H5Torder.lo \ - H5Tpad.lo H5Tprecis.lo H5Tstrpad.lo H5Tvlen.lo H5TS.lo H5V.lo \ - H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo \ - H5Zszip.lo H5Zscaleoffset.lo H5Ztrans.lo + H5Fsfile.lo H5Fsuper.lo H5FD.lo H5FDcore.lo H5FDfamily.lo \ + H5FDfphdf5.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \ + H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDstdio.lo \ + H5FDstream.lo H5FL.lo H5FO.lo H5FP.lo H5FPclient.lo \ + H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo H5Gnode.lo H5Gstab.lo \ + H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo H5I.lo H5MF.lo \ + H5MM.lo H5MP.lo H5MPtest.lo H5O.lo H5Oattr.lo H5Obogus.lo \ + H5Ocont.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Olayout.lo \ + H5Omtime.lo H5Oname.lo H5Onull.lo H5Opline.lo H5Osdspace.lo \ + H5Oshared.lo H5Ostab.lo H5P.lo H5Pdcpl.lo H5Pdxpl.lo \ + H5Pfapl.lo H5Pfcpl.lo H5Pocpl.lo H5Ptest.lo H5R.lo H5RC.lo \ + H5RS.lo H5S.lo H5Sall.lo H5Shyper.lo H5Smpio.lo H5Snone.lo \ + H5Spoint.lo H5Sselect.lo H5Stest.lo H5SH.lo H5SHcache.lo \ + H5SHdbg.lo H5SL.lo H5ST.lo H5T.lo H5Tarray.lo H5Tbit.lo \ + H5Tcommit.lo H5Tcompound.lo H5Tconv.lo H5Tcset.lo H5Tenum.lo \ + H5Tfields.lo H5Tfixed.lo H5Tfloat.lo H5Tinit.lo H5Tnative.lo \ + H5Toffset.lo H5Topaque.lo H5Torder.lo H5Tpad.lo H5Tprecis.lo \ + H5Tstrpad.lo H5Tvlen.lo H5TS.lo H5V.lo H5Z.lo H5Zdeflate.lo \ + H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo H5Zszip.lo \ + H5Zscaleoffset.lo H5Ztrans.lo libhdf5_la_OBJECTS = $(am_libhdf5_la_OBJECTS) PROGRAMS = $(noinst_PROGRAMS) H5detect_SOURCES = H5detect.c @@ -380,7 +381,7 @@ libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2cache.c H5B2dbg.c \ H5Dcontig.c \ H5Dcompact.c \ H5Defl.c H5Dio.c H5Distore.c H5Dmpio.c H5Dselect.c H5Dtest.c H5E.c H5F.c \ - H5Fdbg.c H5Fmount.c H5Fsuper.c H5FD.c H5FDcore.c \ + H5Fdbg.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5FD.c H5FDcore.c \ H5FDfamily.c H5FDfphdf5.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \ H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c \ @@ -583,6 +584,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FS.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmount.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsfile.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsuper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5G.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gent.Plo@am__quote@ diff --git a/test/mount.c b/test/mount.c index 4813fa0..762c7b1 100644 --- a/test/mount.c +++ b/test/mount.c @@ -19,6 +19,7 @@ * Purpose: Tests file mounting. */ #include "h5test.h" +#include "H5Fprivate.h" /* File access */ #include "H5Iprivate.h" /* IDs */ const char *FILENAME[] = { @@ -26,6 +27,9 @@ const char *FILENAME[] = { "mount_2", "mount_3", "mount_4", + "mount_5", + "mount_6", + "mount_7", NULL }; @@ -1004,6 +1008,8 @@ test_close(hid_t fapl) /* Check that all file IDs have been closed */ if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR /* Build the virtual file again */ if ((file1=H5Fopen(filename1, H5F_ACC_RDWR, fapl))<0 || @@ -1021,6 +1027,8 @@ test_close(hid_t fapl) /* Check that all file IDs have been closed */ if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR /* Shut down */ PASSED(); @@ -1665,6 +1673,8 @@ test_missing_unmount(hid_t fapl) /* Check that all file IDs have been closed */ if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR PASSED(); return 0; @@ -1799,6 +1809,8 @@ test_hold_open_file(hid_t fapl) /* Check that all file IDs have been closed */ if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR PASSED(); return 0; @@ -1954,6 +1966,8 @@ test_hold_open_group(hid_t fapl) /* Check that all file IDs have been closed */ if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR PASSED(); return 0; @@ -2098,6 +2112,8 @@ test_fcdegree_same(hid_t fapl) /* Check that all file IDs have been closed */ if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR PASSED(); return 0; @@ -2238,6 +2254,8 @@ test_fcdegree_semi(hid_t fapl) /* Check that all file IDs have been closed */ if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR PASSED(); return 0; @@ -2374,6 +2392,8 @@ test_fcdegree_strong(hid_t fapl) /* Check that all file IDs have been closed */ if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR PASSED(); return 0; @@ -2576,6 +2596,8 @@ test_acc_perm(hid_t fapl) /* Check that all file IDs have been closed */ if(H5I_nmembers(H5I_FILE) != 0) TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR PASSED(); return 0; @@ -2594,7 +2616,1183 @@ error: } H5E_END_TRY; return 1; } /* end test_acc_perm() */ + + +/*------------------------------------------------------------------------- + * Function: test_mult_mount + * + * Purpose: Test that the library correctly handles mounting a file + * multiple times at different locations in the parent file(s) + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Monday, July 25, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_mult_mount(hid_t fapl) +{ + hid_t fid1 = -1, fid2 = -1, fid3 = -1, fid3_2 = -1; /* File IDs */ + hid_t gidA = -1, gidB = -1; /* Group IDs in file #1 */ + hid_t gidM = -1, gidN = -1, gidAM = -1; /* Group IDs in file #2 */ + hid_t gidS = -1, gidT = -1, gidU = -1, gidBS = -1, gidAMT = -1; /* Group IDs in file #3 */ + char name[NAME_BUF_SIZE]; /* Buffer for filename retrieved */ + char filename1[1024], + filename2[1024], + filename3[1024]; /* Name of files to mount */ + + TESTING("multiple mounts"); + + h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2); + h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3); + + /* 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((gidB = H5Gcreate(fid1, "B", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidB) < 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((gidN = H5Gcreate(fid2, "N", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidN) < 0) + TEST_ERROR + + if(H5Fclose(fid2) < 0) + TEST_ERROR + + + /* Create file #3 */ + if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidS = H5Gcreate(fid3, "S", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidS) < 0) + TEST_ERROR + + if((gidT = H5Gcreate(fid3, "T", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidT) < 0) + TEST_ERROR + + if(H5Fclose(fid3) < 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((gidB = H5Gopen(fid1, "B")) < 0) + TEST_ERROR + + if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Mount files together */ + if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0) + TEST_ERROR + + /* Open group in mounted file */ + if((gidAM = H5Gopen(fid1, "A/M")) < 0) + TEST_ERROR + + /* Open file #3 again */ + if((fid3 = H5Fopen(filename3, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Mount file #3 on file #2 */ + if(H5Fmount(gidAM, ".", fid3, H5P_DEFAULT) < 0) + TEST_ERROR + + /* Re-open file #3 */ + if((fid3_2 = H5Freopen(fid3)) < 0) + TEST_ERROR + + /* Mount file #3 on file #1 also */ + if(H5Fmount(gidB, ".", fid3_2, H5P_DEFAULT) < 0) + TEST_ERROR + + /* Open object in file #3 through file #2 mount path */ + if((gidAMT = H5Gopen(fid1, "A/M/T")) < 0) + TEST_ERROR + + /* Check name */ + if(H5Iget_name(gidAMT, name, (size_t)NAME_BUF_SIZE ) < 0) + TEST_ERROR + if(HDstrcmp(name, "/A/M/T")) + TEST_ERROR + + /* Create object in file #3 */ + if((gidU = H5Gcreate(gidAMT, "U", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidU) < 0) + TEST_ERROR + + /* Open object in file #3 through file #1 mount path */ + if((gidBS = H5Gopen(fid1, "B/S")) < 0) + TEST_ERROR + + /* Check name */ + if(H5Iget_name(gidBS, name, (size_t)NAME_BUF_SIZE ) < 0) + TEST_ERROR + if(HDstrcmp(name, "/B/S")) + TEST_ERROR + + /* Re-open object created in file #3 through file #1 mount path */ + if((gidU = H5Gopen(gidBS, "/B/T/U")) < 0) + TEST_ERROR + + if(H5Gclose(gidU) < 0) + TEST_ERROR + + /* Close groups in file #3 */ + if(H5Gclose(gidBS) < 0) + TEST_ERROR + if(H5Gclose(gidAMT) < 0) + TEST_ERROR + + /* Close group in file #2 */ + if(H5Gclose(gidAM) < 0) + TEST_ERROR + + /* Close groups in file #1 */ + if(H5Gclose(gidA) < 0) + TEST_ERROR + if(H5Gclose(gidB) < 0) + TEST_ERROR + + /* Close file #3 IDs */ + if(H5Fclose(fid3) < 0) + TEST_ERROR + if(H5Fclose(fid3_2) < 0) + TEST_ERROR + + /* Close file #2 */ + if(H5Fclose(fid2) < 0) + TEST_ERROR + + /* Close file #1 */ + if(H5Fclose(fid1) < 0) + TEST_ERROR + + + /* Check that all file IDs have been closed */ + if(H5I_nmembers(H5I_FILE) != 0) + TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gidU); + H5Gclose(gidAMT); + H5Gclose(gidT); + H5Gclose(gidBS); + H5Gclose(gidS); + H5Gclose(gidAM); + H5Gclose(gidN); + H5Gclose(gidM); + H5Gclose(gidB); + H5Gclose(gidA); + H5Fclose(fid3_2); + H5Fclose(fid3); + H5Fclose(fid2); + H5Fclose(fid1); + } H5E_END_TRY; + return 1; +} /* end test_mult_mount() */ + + +/*------------------------------------------------------------------------- + * Function: test_nested_survive + * + * Purpose: Test that the library correctly handles unmounting & remounting + * a file with files mounted on it + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Monday, July 25, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_nested_survive(hid_t fapl) +{ + hid_t fid1 = -1, fid2 = -1, fid3 = -1; /* File IDs */ + hid_t gidA = -1; /* Group IDs in file #1 */ + hid_t gidM = -1, gidAM = -1; /* Group IDs in file #2 */ + hid_t gidS = -1, gidMS = -1, gidAMS = -1; /* Group IDs in file #3 */ + char name[NAME_BUF_SIZE]; /* Buffer for filename retrieved */ + ssize_t name_len; /* Filename length */ + char filename1[1024], + filename2[1024], + filename3[1024]; /* Name of files to mount */ + + TESTING("nested mounts survive"); + + h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2); + h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3); + /* 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 + + + /* Create file #3 */ + if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidS = H5Gcreate(fid3, "S", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidS) < 0) + TEST_ERROR + + if(H5Fclose(fid3) < 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 + + /* Mount files together */ + if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0) + TEST_ERROR + + /* Open group in mounted file */ + if((gidAM = H5Gopen(fid1, "A/M")) < 0) + TEST_ERROR + + /* Open file #3 again */ + if((fid3 = H5Fopen(filename3, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Mount file #3 on file #2 */ + if(H5Fmount(gidAM, ".", fid3, H5P_DEFAULT) < 0) + TEST_ERROR + + /* Open object in file #3 through file #1 mount path */ + if((gidAMS = H5Gopen(fid1, "A/M/S")) < 0) + TEST_ERROR + + /* Close group in file #3 */ + if(H5Gclose(gidAMS) < 0) + TEST_ERROR + + /* Check name */ + if((name_len = H5Iget_name(gidAM, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len == 0 || HDstrcmp(name, "/A/M")) + TEST_ERROR + + /* Unmount file #2 from file #1 */ + if(H5Funmount(gidA, ".") < 0) + TEST_ERROR + + /* Check name (should be unavailable) */ + if((name_len = H5Iget_name(gidAM, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len != 0) + TEST_ERROR + + /* Open object in file #3 through file #1 mount path (should fail) */ + H5E_BEGIN_TRY { + gidAMS = H5Gopen(fid1, "A/M/S"); + } H5E_END_TRY; + if(gidAMS >= 0) + TEST_ERROR + + /* Open object in file #3 through file #2 mount path */ + if((gidMS = H5Gopen(fid2, "M/S")) < 0) + TEST_ERROR + + /* Check name */ + if(H5Iget_name(gidMS, name, (size_t)NAME_BUF_SIZE ) < 0) + TEST_ERROR + if(HDstrcmp(name, "/M/S")) + TEST_ERROR + + /* Close group in file #3 */ + if(H5Gclose(gidMS) < 0) + TEST_ERROR + + /* Re-mount file #2 on file #1 */ + if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0) + TEST_ERROR + + /* Open object in file #3 through file #1 mount path again */ + if((gidAMS = H5Gopen(fid1, "A/M/S")) < 0) + TEST_ERROR + + /* Check name */ + if(H5Iget_name(gidAMS, name, (size_t)NAME_BUF_SIZE ) < 0) + TEST_ERROR + if(HDstrcmp(name, "/A/M/S")) + TEST_ERROR + + /* Close group in file #3 */ + if(H5Gclose(gidAMS) < 0) + TEST_ERROR + + /* Close group in file #2 */ + if(H5Gclose(gidAM) < 0) + TEST_ERROR + + /* Close groups in file #1 */ + if(H5Gclose(gidA) < 0) + TEST_ERROR + + /* Close file #3 IDs */ + if(H5Fclose(fid3) < 0) + TEST_ERROR + + /* Close file #2 */ + if(H5Fclose(fid2) < 0) + TEST_ERROR + + /* Close file #1 */ + if(H5Fclose(fid1) < 0) + TEST_ERROR + + + /* Check that all file IDs have been closed */ + if(H5I_nmembers(H5I_FILE) != 0) + TEST_ERROR + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gidAMS); + H5Gclose(gidMS); + H5Gclose(gidS); + H5Gclose(gidAM); + H5Gclose(gidM); + H5Gclose(gidA); + H5Fclose(fid3); + H5Fclose(fid2); + H5Fclose(fid1); + } H5E_END_TRY; + return 1; +} /* end test_nested_survive() */ + + +/*------------------------------------------------------------------------- + * Function: test_close_parent + * + * Purpose: Test that the library correctly handles holding open a child + * file while unmounting & closing parent. + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Monday, July 25, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_close_parent(hid_t fapl) +{ + hid_t fid1 = -1, fid2 = -1; /* File IDs */ + hid_t gidA = -1; /* Group IDs in file #1 */ + hid_t gidM = -1; /* Group IDs in file #2 */ + char name[NAME_BUF_SIZE]; /* Buffer for filename retrieved */ + ssize_t name_len; /* Filename length */ + char filename1[1024], + filename2[1024]; /* Name of files to mount */ + + TESTING("close parent"); + + 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 + + /* Mount files together */ + if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0) + TEST_ERROR + + /* Open group in mounted file */ + if((gidM = H5Gopen(fid1, "A/M")) < 0) + TEST_ERROR + + /* Close group in file #1 */ + if(H5Gclose(gidA) < 0) + TEST_ERROR + + /* Close files #1 & #2 */ + if(H5Fclose(fid1) < 0) + TEST_ERROR + if(H5Fclose(fid2) < 0) + TEST_ERROR + + /* Check that all file IDs have been closed */ + if(H5I_nmembers(H5I_FILE) != 0) + TEST_ERROR + + /* Both underlying shared files should be open still */ + if(H5F_sfile_assert_num(2) != 0) + TEST_ERROR + + /* Check the name of "M" is still defined */ + if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len == 0 || HDstrcmp(name, "/A/M")) + TEST_ERROR + + /* Unmount file #2 from file #1, closing file #1 */ + if(H5Funmount(gidM, "/A") < 0) + TEST_ERROR + + /* Check the name of "M" is not defined any longer */ + if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len != 0) + TEST_ERROR + + /* Just file #2's underlying shared file should be open still */ + if(H5F_sfile_assert_num(1) != 0) + TEST_ERROR + + /* Close group in file #2, letting file #2 close */ + if(H5Gclose(gidM) < 0) + TEST_ERROR + + /* All underlying shared file structs should be closed */ + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gidM); + H5Gclose(gidA); + H5Fclose(fid2); + H5Fclose(fid1); + } H5E_END_TRY; + return 1; +} /* end test_close_parent() */ + + +/*------------------------------------------------------------------------- + * Function: test_cut_graph + * + * Purpose: Test that the library correctly handles cutting a graph of + * mounted files. + * + * Initial file mounting graph is built up to this: + * + * [1] + * / \ + * / \ + * "A" "B" + * / \ + * / \ + * [2] [3] + * / \ / \ + * "D" "E" "H" "I" + * / \ / \ + * [4] [5] [6] [7] + * | | | | + * "K" "M" "O" "Q" + * + * ( where [n] is a file in mounting hierarchy and "X" is a group + * in a file ) + * + * Objects in file #5 & file #7 are opened and all other + * file & object IDs to the hierarchy are closed. + * + * Then file #2 is unmounted from file #1, which should make a + * small tree of files 2, 4 & 5 and a larger tree of files 1, 3, + * 6 & 7. + * + * Then, the object in file #5 is closed, which should release its + * small tree of files. + * + * Then, file #3 is unmounted from file #1, making it's tree + * only 3, 6 & 7. + * + * Then, the object in file #7 is closed, which should release the + * remaining small tree of files. + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Monday, July 25, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_cut_graph(hid_t fapl) +{ + hid_t fid1 = -1, fid2 = -1, fid3 = -1, + fid4 = -1, fid5 = -1, fid6 = -1, fid7 = -1; /* File IDs */ + hid_t gidA = -1, gidB = -1; /* Group IDs in file #1 */ + hid_t gidD = -1, gidE = -1; /* Group IDs in file #2 */ + hid_t gidH = -1, gidI = -1; /* Group IDs in file #3 */ + hid_t gidK = -1; /* Group IDs in file #4 */ + hid_t gidM = -1; /* Group IDs in file #5 */ + hid_t gidO = -1; /* Group IDs in file #6 */ + hid_t gidQ = -1; /* Group IDs in file #7 */ + char name[NAME_BUF_SIZE]; /* Buffer for filename retrieved */ + ssize_t name_len; /* Filename length */ + int obj_count; /* Number of objects open */ + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE], + filename3[NAME_BUF_SIZE], + filename4[NAME_BUF_SIZE], + filename5[NAME_BUF_SIZE], + filename6[NAME_BUF_SIZE], + filename7[NAME_BUF_SIZE]; /* Name of files to mount */ + + TESTING("cutting mount graph"); + + h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2); + h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3); + h5_fixname(FILENAME[3], fapl, filename4, sizeof filename3); + h5_fixname(FILENAME[4], fapl, filename5, sizeof filename3); + h5_fixname(FILENAME[5], fapl, filename6, sizeof filename3); + h5_fixname(FILENAME[6], fapl, filename7, sizeof filename3); + + /* Create file #1 & it's groups */ + 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((gidB = H5Gcreate(fid1, "B", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidB) < 0) + TEST_ERROR + + if(H5Fclose(fid1) < 0) + TEST_ERROR + + + /* Create file #2 & it's groups */ + if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidD = H5Gcreate(fid2, "D", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidD) < 0) + TEST_ERROR + + if((gidE = H5Gcreate(fid2, "E", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidE) < 0) + TEST_ERROR + + if(H5Fclose(fid2) < 0) + TEST_ERROR + + + /* Create file #3 & it's groups */ + if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidH = H5Gcreate(fid3, "H", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidH) < 0) + TEST_ERROR + + if((gidI = H5Gcreate(fid3, "I", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidI) < 0) + TEST_ERROR + + if(H5Fclose(fid3) < 0) + TEST_ERROR + + /* Create file #4 & it's group */ + if((fid4 = H5Fcreate(filename4, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidK = H5Gcreate(fid4, "K", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidK) < 0) + TEST_ERROR + + if(H5Fclose(fid4) < 0) + TEST_ERROR + + /* Create file #5 & it's group */ + if((fid5 = H5Fcreate(filename5, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidM = H5Gcreate(fid5, "M", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidM) < 0) + TEST_ERROR + + if(H5Fclose(fid5) < 0) + TEST_ERROR + + /* Create file #6 & it's group */ + if((fid6 = H5Fcreate(filename6, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidO = H5Gcreate(fid6, "O", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidO) < 0) + TEST_ERROR + + if(H5Fclose(fid6) < 0) + TEST_ERROR + + /* Create file #7 & it's group */ + if((fid7 = H5Fcreate(filename7, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidQ = H5Gcreate(fid7, "Q", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidQ) < 0) + TEST_ERROR + + if(H5Fclose(fid7) < 0) + TEST_ERROR + + + /* Re-open files and build mount hierarchy */ + if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Mount file #2 at /A */ + if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + if(H5Fmount(fid1, "/A", fid2, H5P_DEFAULT) < 0) + TEST_ERROR + if(H5Fclose(fid2) < 0) + TEST_ERROR + + /* Mount file #3 at /B */ + if((fid3 = H5Fopen(filename3, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + if(H5Fmount(fid1, "/B", fid3, H5P_DEFAULT) < 0) + TEST_ERROR + if(H5Fclose(fid3) < 0) + TEST_ERROR + + /* Mount file #4 at /A/D */ + if((fid4 = H5Fopen(filename4, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + if(H5Fmount(fid1, "/A/D", fid4, H5P_DEFAULT) < 0) + TEST_ERROR + if(H5Fclose(fid4) < 0) + TEST_ERROR + + /* Mount file #5 at /A/E */ + if((fid5 = H5Fopen(filename5, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + if(H5Fmount(fid1, "/A/E", fid5, H5P_DEFAULT) < 0) + TEST_ERROR + if(H5Fclose(fid5) < 0) + TEST_ERROR + + /* Mount file #6 at /B/H */ + if((fid6 = H5Fopen(filename6, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + if(H5Fmount(fid1, "/B/H", fid6, H5P_DEFAULT) < 0) + TEST_ERROR + if(H5Fclose(fid6) < 0) + TEST_ERROR + + /* Mount file #7 at /B/H */ + if((fid7 = H5Fopen(filename7, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + if(H5Fmount(fid1, "/B/I", fid7, H5P_DEFAULT) < 0) + TEST_ERROR + if(H5Fclose(fid7) < 0) + TEST_ERROR + + /* Open object in file #5 */ + if((gidM = H5Gopen(fid1, "A/E/M")) < 0) + TEST_ERROR + + /* Check name */ + if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len == 0 || HDstrcmp(name, "/A/E/M")) + TEST_ERROR + + /* Open object in file #7 */ + if((gidQ = H5Gopen(fid1, "B/I/Q")) < 0) + TEST_ERROR + + /* Check name */ + if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len == 0 || HDstrcmp(name, "/B/I/Q")) + TEST_ERROR + + /* Close file #1 */ + if(H5Fclose(fid1) < 0) + TEST_ERROR + + + /* Get a new file ID for file #5 */ + if((fid5 = H5Iget_file_id(gidM)) < 0) + TEST_ERROR + + /* Check the number of objects currently open */ + if((obj_count = H5Fget_obj_count(fid5, H5F_OBJ_ALL)) < 0) + TEST_ERROR + if(obj_count != 2) /* one object and the file ID */ + TEST_ERROR + + /* Close ID on file #5 */ + if(H5Fclose(fid5) < 0) + TEST_ERROR + + + /* Get a new file ID for file #7 */ + if((fid7 = H5Iget_file_id(gidQ)) < 0) + TEST_ERROR + + /* Check the number of objects currently open */ + if((obj_count = H5Fget_obj_count(fid7, H5F_OBJ_ALL)) < 0) + TEST_ERROR + if(obj_count != 2) /* one object and the file ID */ + TEST_ERROR + + /* Close ID on file #7 */ + if(H5Fclose(fid7) < 0) + TEST_ERROR + + /* Check that all file IDs have been closed */ + if(H5I_nmembers(H5I_FILE) != 0) + TEST_ERROR + + + /* Unmount file #2 from file #1, cutting the graph */ + if(H5Funmount(gidM, "/A") < 0) + TEST_ERROR + + /* Attempt to open an object in file #4, from file #1 */ + H5E_BEGIN_TRY { + gidK = H5Gopen(gidQ, "/A/D/K"); + } H5E_END_TRY; + if(gidK >= 0) + TEST_ERROR + + /* Open object in file #4 from file #5 */ + if((gidK = H5Gopen(gidM, "/D/K")) < 0) + TEST_ERROR + + /* Check the name of "K" is correct */ + if((name_len = H5Iget_name(gidK, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len == 0 || HDstrcmp(name, "/D/K")) + TEST_ERROR + + if(H5Gclose(gidK) < 0) + TEST_ERROR + + /* Attempt to open an object in file #6, from file #5 */ + H5E_BEGIN_TRY { + gidO = H5Gopen(gidM, "/B/H/O"); + } H5E_END_TRY; + if(gidO >= 0) + TEST_ERROR + + /* Open object in file #6 from file #7 */ + if((gidO = H5Gopen(gidQ, "/B/H/O")) < 0) + TEST_ERROR + + /* Check the name of "O" is correct */ + if((name_len = H5Iget_name(gidO, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len == 0 || HDstrcmp(name, "/B/H/O")) + TEST_ERROR + + if(H5Gclose(gidO) < 0) + TEST_ERROR + + /* Check the name of "M" is not defined any longer */ + if((name_len = H5Iget_name(gidM, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len != 0) + TEST_ERROR + + /* Check the name of "Q" is still defined */ + if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len == 0 || HDstrcmp(name, "/B/I/Q")) + TEST_ERROR + + /* Check that all seven underlying files are still opened */ + if(H5F_sfile_assert_num(7) != 0) + TEST_ERROR + + /* Close "M" in file #5, which should close files 2, 4 & 5 */ + if(H5Gclose(gidM) < 0) + TEST_ERROR + + /* Check that only four underlying files are still opened */ + if(H5F_sfile_assert_num(4) != 0) + TEST_ERROR + + /* Unmount file #3 from file #1, cutting the graph */ + if(H5Funmount(gidQ, "/B") < 0) + TEST_ERROR + + /* Check that only three underlying files are still opened */ + /* (File #1 should close after being cut off from the graph) */ + if(H5F_sfile_assert_num(3) != 0) + TEST_ERROR + + /* Check the name of "Q" is not defined any longer */ + if((name_len = H5Iget_name(gidQ, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len != 0) + TEST_ERROR + + /* Open object in file #6 from file #7 */ + if((gidO = H5Gopen(gidQ, "/H/O")) < 0) + TEST_ERROR + + /* Check the name of "O" is correct */ + if((name_len = H5Iget_name(gidO, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len == 0 || HDstrcmp(name, "/H/O")) + TEST_ERROR + + if(H5Gclose(gidO) < 0) + TEST_ERROR + + /* Close last object and let files 3, 6 & 7 close */ + if(H5Gclose(gidQ) < 0) + TEST_ERROR + + /* Verify that all underlying shared files have been closed now */ + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gidQ); + H5Gclose(gidO); + H5Gclose(gidM); + H5Gclose(gidK); + H5Gclose(gidI); + H5Gclose(gidH); + H5Gclose(gidE); + H5Gclose(gidD); + H5Gclose(gidB); + H5Gclose(gidA); + H5Fclose(fid7); + H5Fclose(fid6); + H5Fclose(fid5); + H5Fclose(fid4); + H5Fclose(fid3); + H5Fclose(fid2); + H5Fclose(fid1); + } H5E_END_TRY; + return 1; +} /* end test_cut_graph() */ + + +/*------------------------------------------------------------------------- + * Function: test_symlink + * + * Purpose: Test that the library correctly handles symlinks across + * mounted files. + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Monday, July 25, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_symlink(hid_t fapl) +{ + hid_t fid1 = -1, fid2 = -1, fid3 = -1; /* File IDs */ + hid_t gidA = -1, gidB = -1; /* Group IDs in file #1 */ + hid_t gidD = -1, gidE = -1; /* Group IDs in file #2 */ + hid_t gidH = -1, gidI = -1; /* Group IDs in file #3 */ + hid_t gidL = -1; /* Group IDs through soft link to file #3 */ + char name[NAME_BUF_SIZE]; /* Buffer for filename retrieved */ + ssize_t name_len; /* Filename length */ + char filename1[NAME_BUF_SIZE], + filename2[NAME_BUF_SIZE], + filename3[NAME_BUF_SIZE]; /* Name of files to mount */ + + TESTING("symlinks"); + + h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2); + h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3); + + /* Create file #1 & it's groups */ + 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((gidB = H5Gcreate(fid1, "B", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidB) < 0) + TEST_ERROR + + /* Create soft link to mounted object */ + if(H5Glink(fid1, H5G_LINK_SOFT, "./A/D/H", "L") < 0) /* Soft link */ + TEST_ERROR + + if(H5Fclose(fid1) < 0) + TEST_ERROR + + + /* Create file #2 & it's groups */ + if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidD = H5Gcreate(fid2, "D", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidD) < 0) + TEST_ERROR + + if((gidE = H5Gcreate(fid2, "E", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidE) < 0) + TEST_ERROR + + if(H5Fclose(fid2) < 0) + TEST_ERROR + + + /* Create file #3 & it's groups */ + if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidH = H5Gcreate(fid3, "H", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidH) < 0) + TEST_ERROR + + if((gidI = H5Gcreate(fid3, "I", (size_t)0)) < 0) + TEST_ERROR + if(H5Gclose(gidI) < 0) + TEST_ERROR + + if(H5Fclose(fid3) < 0) + TEST_ERROR + + + /* Re-open files and build mount hierarchy */ + if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + + /* Mount file #2 at /A */ + if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + if(H5Fmount(fid1, "/A", fid2, H5P_DEFAULT) < 0) + TEST_ERROR + if(H5Fclose(fid2) < 0) + TEST_ERROR + + /* Attempt to open an object in file #3 (should fail) */ + H5E_BEGIN_TRY { + gidL = H5Gopen(fid1, "L"); + } H5E_END_TRY; + if(gidL >= 0) + TEST_ERROR + + /* Mount file #3 at /A/D */ + if((fid3 = H5Fopen(filename3, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + if(H5Fmount(fid1, "/A/D", fid3, H5P_DEFAULT) < 0) + TEST_ERROR + if(H5Fclose(fid3) < 0) + TEST_ERROR + + /* Open soft link to object in file #3 */ + if((gidL = H5Gopen(fid1, "L")) < 0) + TEST_ERROR + + /* Check the name of "L" is correct */ + if((name_len = H5Iget_name(gidL, name, (size_t)NAME_BUF_SIZE )) < 0) + TEST_ERROR + if(name_len == 0 || HDstrcmp(name, "/L")) + TEST_ERROR + + /* Close file #1 */ + if(H5Fclose(fid1) < 0) + TEST_ERROR + + /* Verify that all 3 underlying shared files are still open */ + if(H5F_sfile_assert_num(3) != 0) + TEST_ERROR + + /* Close object opened through soft link */ + if(H5Gclose(gidL) < 0) + TEST_ERROR + + /* Verify that all underlying shared files have been closed now */ + if(H5F_sfile_assert_num(0) != 0) + TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gidL); + H5Gclose(gidI); + H5Gclose(gidH); + H5Gclose(gidE); + H5Gclose(gidD); + H5Gclose(gidB); + H5Gclose(gidA); + H5Fclose(fid3); + H5Fclose(fid2); + H5Fclose(fid1); + } H5E_END_TRY; + return 1; +} /* end test_symlink() */ + /*------------------------------------------------------------------------- * Function: main @@ -2644,6 +3842,11 @@ main(void) nerrors += test_fcdegree_semi(fapl); nerrors += test_fcdegree_strong(fapl); nerrors += test_acc_perm(fapl); + nerrors += test_mult_mount(fapl); + nerrors += test_nested_survive(fapl); + nerrors += test_close_parent(fapl); + nerrors += test_cut_graph(fapl); + nerrors += test_symlink(fapl); if (nerrors) goto error; puts("All mount tests passed."); diff --git a/test/tfile.c b/test/tfile.c index 05a0765..ece7cdb 100644 --- a/test/tfile.c +++ b/test/tfile.c @@ -576,6 +576,10 @@ test_file_close(void) ret = H5Fclose(fid2); VERIFY(ret, FAIL, "H5Fclose"); + /* Same check with H5Idec_ref() (should fail also) */ + ret = H5Idec_ref(fid2); + VERIFY(ret, FAIL, "H5Idec_ref"); + ret = H5Gclose(group_id3); CHECK(ret, FAIL, "H5Gclose"); diff --git a/tools/h5diff/h5diff_common.c b/tools/h5diff/h5diff_common.c index 51ba881..691fe8a 100644 --- a/tools/h5diff/h5diff_common.c +++ b/tools/h5diff/h5diff_common.c @@ -131,7 +131,7 @@ void parse_input(int argc, const char* argv[], const char** fname1, const char** printf("<-n %s> is not a valid option\n", argv[i+1] ); usage(); } - options->count = atoi(argv[i+1]); + options->count = atol(argv[i+1]); i++; /* go to next */ } else diff --git a/tools/lib/h5diff.h b/tools/lib/h5diff.h index cdaabaa..a307cb8 100644 --- a/tools/lib/h5diff.h +++ b/tools/lib/h5diff.h @@ -59,7 +59,7 @@ typedef struct { int p; /* relative error to compare*/ double percent; /* relative error value */ int n; /* count, compare up to count */ - int count; /* count value */ + hsize_t count; /* count value */ int err_stat; /* an error ocurred (1, error, 0, no error) */ int cmn_objs; /* do we have comparable objects */ int not_cmp; /* are the objects comparable */ -- cgit v0.12