diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2010-07-22 17:04:48 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2010-07-22 17:04:48 (GMT) |
commit | 2ae193a0383a75c365c1cb2116428dc173c1610d (patch) | |
tree | e2e84fb762d9946a91b4a288ca6835688864087c | |
parent | 87748c6a0b5d3aba7cfce54746ebae2f5caeebc6 (diff) | |
download | hdf5-2ae193a0383a75c365c1cb2116428dc173c1610d.zip hdf5-2ae193a0383a75c365c1cb2116428dc173c1610d.tar.gz hdf5-2ae193a0383a75c365c1cb2116428dc173c1610d.tar.bz2 |
[svn-r19123] Description:
Converge code on "metadata journaling merge" branch to be closer to
code on current trunk:
- Updates to internal error reporting macros
- Updated routines to operation on superblock extension
- Object header query operations
Misc. minor updates to caching code.
Tested on:
FreeBSD/32 6.3 (duty) in debug mode
FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (jam) w/PGI compilers, w/default API=1.8.x,
w/C++ & FORTRAN, w/threadsafe, in debug mode
Linux/64-amd64 2.6 (amani) w/Intel compilers, w/default API=1.6.x,
w/C++ & FORTRAN, in production mode
Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN,
w/szip filter, w/threadsafe, in production mode
Linux/PPC 2.6 (heiwa) w/C++ & FORTRAN, w/threadsafe, in debug mode
Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN,
in production mode
Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in debug mode
Mac OS X/32 10.6.4 (amazon) in debug mode
Mac OS X/32 10.6.4 (amazon) w/C++ & FORTRAN, w/threadsafe,
in production mode
Mac OS X/32 10.6.4 (amazon) w/parallel, in debug mode
-rw-r--r-- | src/H5AC.c | 2 | ||||
-rw-r--r-- | src/H5C.c | 5 | ||||
-rw-r--r-- | src/H5Eint.c | 101 | ||||
-rw-r--r-- | src/H5Eprivate.h | 41 | ||||
-rw-r--r-- | src/H5Fpkg.h | 5 | ||||
-rw-r--r-- | src/H5Fsuper.c | 303 | ||||
-rw-r--r-- | src/H5O.c | 179 | ||||
-rw-r--r-- | src/H5Oprivate.h | 1 | ||||
-rw-r--r-- | src/H5Opublic.h | 35 |
9 files changed, 552 insertions, 120 deletions
@@ -1741,7 +1741,7 @@ H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "can't log dirtied entry") } - if ( ( (flags & H5C__DELETED_FLAG) != 0 ) && + if ( ( deleted ) && ( NULL != (aux_ptr = f->shared->cache->aux_ptr) ) && ( aux_ptr->mpi_rank == 0 ) ) { @@ -223,7 +223,6 @@ H5C_epoch_marker_load(H5F_t UNUSED * f, HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, NULL, "called unreachable fcn.") done: - FUNC_LEAVE_NOAPI(ret_value) } @@ -242,7 +241,6 @@ H5C_epoch_marker_flush(H5F_t UNUSED *f, HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "called unreachable fcn.") done: - FUNC_LEAVE_NOAPI(ret_value) } @@ -257,7 +255,6 @@ H5C_epoch_marker_dest(H5F_t UNUSED * f, HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "called unreachable fcn.") done: - FUNC_LEAVE_NOAPI(ret_value) } @@ -273,7 +270,6 @@ H5C_epoch_marker_clear(H5F_t UNUSED * f, HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "called unreachable fcn.") done: - FUNC_LEAVE_NOAPI(ret_value) } @@ -289,7 +285,6 @@ H5C_epoch_marker_size(const H5F_t UNUSED * f, HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "called unreachable fcn.") done: - FUNC_LEAVE_NOAPI(ret_value) } diff --git a/src/H5Eint.c b/src/H5Eint.c index e0fa482..92c36a4 100644 --- a/src/H5Eint.c +++ b/src/H5Eint.c @@ -660,6 +660,107 @@ H5E_set_auto(H5E_t *estack, const H5E_auto_op_t *op, void *client_data) /*------------------------------------------------------------------------- + * Function: H5E_printf_stack + * + * Purpose: Printf-like wrapper around H5E_push_stack. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, August 12, 2008 + * + *------------------------------------------------------------------------- + */ +herr_t +H5E_printf_stack(H5E_t *estack, const char *file, const char *func, unsigned line, + hid_t cls_id, hid_t maj_id, hid_t min_id, const char *fmt, ...) +{ + va_list ap; /* Varargs info */ +#ifndef H5_HAVE_VASPRINTF + int tmp_len; /* Current size of description buffer */ + int desc_len; /* Actual length of description when formatted */ +#endif /* H5_HAVE_VASPRINTF */ + char *tmp = NULL; /* Buffer to place formatted description in */ + herr_t ret_value = SUCCEED; /* Return value */ + + /* + * WARNING: We cannot call HERROR() from within this function or else we + * could enter infinite recursion. Furthermore, we also cannot + * call any other HDF5 macro or function which might call + * HERROR(). HERROR() is called by HRETURN_ERROR() which could + * be called by FUNC_ENTER(). + */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_printf_stack) + + /* Sanity check */ + HDassert(cls_id > 0); + HDassert(maj_id > 0); + HDassert(min_id > 0); + HDassert(fmt); + +/* Note that the variable-argument parsing for the format is identical in + * the H5Epush2() routine - correct errors and make changes in both + * places. -QAK + */ + + /* Start the variable-argument parsing */ + va_start(ap, fmt); + +#ifdef H5_HAVE_VASPRINTF + /* Use the vasprintf() routine, since it does what we're trying to do below */ + if(HDvasprintf(&tmp, fmt, ap) < 0) + HGOTO_DONE(FAIL) +#else /* H5_HAVE_VASPRINTF */ + /* Allocate space for the formatted description buffer */ + tmp_len = 128; + if(NULL == (tmp = H5MM_malloc((size_t)tmp_len))) + HGOTO_DONE(FAIL) + + /* If the description doesn't fit into the initial buffer size, allocate more space and try again */ + while((desc_len = HDvsnprintf(tmp, (size_t)tmp_len, fmt, ap)) +#ifdef H5_VSNPRINTF_WORKS + > +#else /* H5_VSNPRINTF_WORKS */ + >= +#endif /* H5_VSNPRINTF_WORKS */ + (tmp_len - 1) +#ifndef H5_VSNPRINTF_WORKS + || (desc_len < 0) +#endif /* H5_VSNPRINTF_WORKS */ + ) { + /* shutdown & restart the va_list */ + va_end(ap); + va_start(ap, fmt); + + /* Release the previous description, it's too small */ + H5MM_xfree(tmp); + + /* Allocate a description of the appropriate length */ +#ifdef H5_VSNPRINTF_WORKS + tmp_len = desc_len + 1; +#else /* H5_VSNPRINTF_WORKS */ + tmp_len = 2 * tmp_len; +#endif /* H5_VSNPRINTF_WORKS */ + if(NULL == (tmp = H5MM_malloc((size_t)tmp_len))) + HGOTO_DONE(FAIL) + } /* end while */ +#endif /* H5_HAVE_VASPRINTF */ + + va_end(ap); + + /* Push the error on the stack */ + if(H5E_push_stack(estack, file, func, line, cls_id, maj_id, min_id, tmp) < 0) + HGOTO_DONE(FAIL) + +done: + if(tmp) + H5MM_xfree(tmp); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5E_printf_stack() */ + + +/*------------------------------------------------------------------------- * Function: H5E_push_stack * * Purpose: Pushes a new error record onto error stack for the current diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h index 05ce10e..0f4cb35 100644 --- a/src/H5Eprivate.h +++ b/src/H5Eprivate.h @@ -32,14 +32,14 @@ typedef struct H5E_t H5E_t; * and a FUNC_LEAVE() within a function body. The arguments are the major * error number, the minor error number, and a description of the error. */ -#define HERROR(maj_id, min_id, str) H5E_push_stack(NULL, __FILE__, FUNC, __LINE__, H5E_ERR_CLS_g, maj_id, min_id, str) +#define HERROR(maj_id, min_id, ...) H5E_printf_stack(NULL, __FILE__, FUNC, __LINE__, H5E_ERR_CLS_g, maj_id, min_id, __VA_ARGS__) /* * HCOMMON_ERROR macro, used by HDONE_ERROR and HGOTO_ERROR * (Shouldn't need to be used outside this header file) */ -#define HCOMMON_ERROR(maj, min, str) \ - HERROR(maj, min, str); \ +#define HCOMMON_ERROR(maj, min, ...) \ + HERROR(maj, min, __VA_ARGS__); \ (void)H5E_dump_api_stack((int)H5_IS_API(FUNC)); /* @@ -51,8 +51,8 @@ typedef struct H5E_t H5E_t; * (This macro can also be used to push an error and set the return value * without jumping to any labels) */ -#define HDONE_ERROR(maj, min, ret_val, str) { \ - HCOMMON_ERROR(maj, min, str); \ +#define HDONE_ERROR(maj, min, ret_val, ...) { \ + HCOMMON_ERROR(maj, min, __VA_ARGS__); \ ret_value = ret_val; \ } @@ -63,8 +63,8 @@ typedef struct H5E_t H5E_t; * error string. The return value is assigned to a variable `ret_value' and * control branches to the `done' label. */ -#define HGOTO_ERROR(maj, min, ret_val, str) { \ - HCOMMON_ERROR(maj, min, str); \ +#define HGOTO_ERROR(maj, min, ret_val, ...) { \ + HCOMMON_ERROR(maj, min, __VA_ARGS__); \ HGOTO_DONE(ret_val) \ } @@ -76,13 +76,6 @@ typedef struct H5E_t H5E_t; */ #define HGOTO_DONE(ret_val) {ret_value = ret_val; goto done;} -/* Library-private functions defined in H5E package */ -H5_DLL herr_t H5E_init(void); -H5_DLL herr_t H5E_push_stack(H5E_t *estack, const char *file, const char *func, unsigned line, - hid_t cls_id, hid_t maj_id, hid_t min_id, const char *desc); -H5_DLL herr_t H5E_clear_stack(H5E_t *estack); -H5_DLL herr_t H5E_dump_api_stack(int is_api); - /* * Macros handling system error messages as described in C standard. * These macros assume errnum is a valid system error code. @@ -91,16 +84,13 @@ H5_DLL herr_t H5E_dump_api_stack(int is_api); /* Retrieve the error code description string and push it onto the error * stack. */ -#define HSYS_ERROR(errnum) { \ - HERROR(H5E_INTERNAL, H5E_SYSERRSTR, HDstrerror(errnum)); \ -} #define HSYS_DONE_ERROR(majorcode, minorcode, retcode, str) { \ - HSYS_ERROR(errno); \ - HDONE_ERROR(majorcode, minorcode, retcode, str); \ + int myerrno = errno; \ + HDONE_ERROR(majorcode, minorcode, retcode, "%s, errno = %d, error message = '%s'", str, myerrno, HDstrerror(myerrno)); \ } #define HSYS_GOTO_ERROR(majorcode, minorcode, retcode, str) { \ - HSYS_ERROR(errno); \ - HGOTO_ERROR(majorcode, minorcode, retcode, str); \ + int myerrno = errno; \ + HGOTO_ERROR(majorcode, minorcode, retcode, "%s, errno = %d, error message = '%s'", str, myerrno, HDstrerror(myerrno)); \ } #ifdef H5_HAVE_PARALLEL @@ -125,5 +115,14 @@ extern int H5E_mpi_error_str_len; } #endif /* H5_HAVE_PARALLEL */ +/* Library-private functions defined in H5E package */ +H5_DLL herr_t H5E_init(void); +H5_DLL herr_t H5E_push_stack(H5E_t *estack, const char *file, const char *func, + unsigned line, hid_t cls_id, hid_t maj_id, hid_t min_id, const char *desc); +H5_DLL herr_t H5E_printf_stack(H5E_t *estack, const char *file, const char *func, + unsigned line, hid_t cls_id, hid_t maj_id, hid_t min_id, const char *fmt, ...); +H5_DLL herr_t H5E_clear_stack(H5E_t *estack); +H5_DLL herr_t H5E_dump_api_stack(int is_api); + #endif /* _H5Eprivate_H */ diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 070d361..387c96f 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -181,8 +181,11 @@ H5_DLL herr_t H5F_mount_count_ids(H5F_t *f, unsigned *nopen_files, unsigned *nop H5_DLL herr_t H5F_super_init(H5F_t *f, hid_t dxpl_id); H5_DLL herr_t H5F_super_write(H5F_t *f, hid_t dxpl_id); H5_DLL herr_t H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc); -H5_DLL herr_t H5F_super_ext_size(H5F_t *f, hid_t dxpl_id, hsize_t *super_ext_info); +/* Superblock extension related routines */ +H5_DLL herr_t H5F_super_ext_size(H5F_t *f, hid_t dxpl_id, hsize_t *super_ext_info); +H5_DLL herr_t H5F_super_ext_write_msg(H5F_t *f, hid_t dxpl_id, void *mesg, unsigned id, hbool_t may_create); +H5_DLL herr_t H5F_super_ext_remove_msg(H5F_t *f, hid_t dxpl_id, unsigned id); /* Shared file list related routines */ H5_DLL herr_t H5F_sfile_add(H5F_file_t *shared); diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index 6e5b940..b01e849 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -108,6 +108,9 @@ /********************/ /* Local Prototypes */ /********************/ +static herr_t H5F_super_ext_create(H5F_t *f, hid_t dxpl_id, H5O_loc_t *ext_ptr); +static herr_t H5F_super_ext_open(H5F_t *f, haddr_t ext_addr, H5O_loc_t *ext_ptr); +static herr_t H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr); /*********************/ @@ -213,6 +216,139 @@ done: /*------------------------------------------------------------------------- + * Function: H5F_super_ext_create + * + * Purpose: Create the superblock extension + * + * Return: Success: non-negative on success + * Failure: Negative + * + * Programmer: Vailin Choi; Feb 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_super_ext_create(H5F_t *f, hid_t dxpl_id, H5O_loc_t *ext_ptr) +{ + H5P_genplist_t *plist; /* File creation property list */ + unsigned super_vers; /* Superblock version */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5F_super_ext_create) + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + HDassert(ext_ptr); + + /* 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 superblock version") + + /* Check for older version of superblock format */ + if(super_vers < HDF5_SUPERBLOCK_VERSION_2) + HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "superblock extension not permitted?!?!") + else if(f->shared->extension_addr != HADDR_UNDEF) + HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "superblock extension already exists?!?!") + else { + /* The superblock extension isn't actually a group, but the + * default group creation list should work fine. + * If we don't supply a size for the object header, HDF5 will + * allocate H5O_MIN_SIZE by default. This is currently + * big enough to hold the biggest possible extension, but should + * be tuned if more information is added to the superblock + * extension. + */ + H5O_loc_reset(ext_ptr); + if(H5O_create(f, dxpl_id, 0, H5P_GROUP_CREATE_DEFAULT, ext_ptr) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "unable to create superblock extension") + + /* Record the address of the superblock extension */ + f->shared->extension_addr = ext_ptr->addr; + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F_super_ext_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_super_ext_open + * + * Purpose: Open an existing superblock extension + * + * Return: Success: non-negative on success + * Failure: Negative + * + * Programmer: Vailin Choi; Feb 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_super_ext_open(H5F_t *f, haddr_t ext_addr, H5O_loc_t *ext_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5F_super_ext_open) + + /* Sanity check */ + HDassert(f); + HDassert(H5F_addr_defined(ext_addr)); + HDassert(ext_ptr); + + /* Set up "fake" object location for superblock extension */ + H5O_loc_reset(ext_ptr); + ext_ptr->file = f; + ext_ptr->addr = ext_addr; + + /* Open the superblock extension object header */ + if(H5O_open(ext_ptr) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open superblock extension") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F_super_ext_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_super_ext_close + * + * Purpose: Close superblock extension + * + * Return: Success: non-negative on success + * Failure: Negative + * + * Programmer: Vailin Choi; Feb 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F_super_ext_close(H5F_t *f, H5O_loc_t *ext_ptr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5F_super_ext_close) + + /* Sanity check */ + HDassert(f); + HDassert(ext_ptr); + + /* Twiddle the number of open objects to avoid closing the file. */ + f->nopen_objs++; + if(H5O_close(ext_ptr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close superblock extension") + f->nopen_objs--; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F_super_ext_close() */ + + +/*------------------------------------------------------------------------- * Function: H5F_super_read * * Purpose: Reads the superblock from the file or from the BUF. If @@ -560,14 +696,9 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) */ HDassert(super_vers >= HDF5_SUPERBLOCK_VERSION_2); - /* Set up "fake" object location for superblock extension */ - H5O_loc_reset(&ext_loc); - ext_loc.file = f; - ext_loc.addr = shared->extension_addr; - /* Open the superblock extension */ - if(H5O_open(&ext_loc) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to open superblock extension") + if(H5F_super_ext_open(f, shared->extension_addr, &ext_loc) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, FAIL, "unable to open file's superblock extension") /* Read in the shared OH message information if there is any */ if(H5SM_get_info(&ext_loc, c_plist, dxpl_id) < 0) @@ -618,13 +749,9 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) H5O_msg_reset(H5O_DRVINFO_ID, &drvinfo); } /* end else */ - /* Close the extension. Twiddle the number of open objects to avoid - * closing the file (since this will be the only open object). - */ - f->nopen_objs++; - if(H5O_close(&ext_loc) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to close superblock extension") - f->nopen_objs--; + /* Close superblock extension */ + if(H5F_super_ext_close(f, &ext_loc) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension") } /* end if */ done: @@ -754,13 +881,9 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id) * be tuned if more information is added to the superblock * extension. */ - H5O_loc_reset(&ext_loc); - if(H5O_create(f, dxpl_id, 0, H5P_GROUP_CREATE_DEFAULT, &ext_loc) < 0) + if(H5F_super_ext_create(f, dxpl_id, &ext_loc) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "unable to create superblock extension") - /* Record the address of the superblock extension */ - f->shared->extension_addr = ext_loc.addr; - /* Create the Shared Object Header Message table and register it with * the metadata cache, if this file supports shared messages. */ @@ -803,13 +926,9 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update driver info header message") } /* end if */ - /* Twiddle the number of open objects to avoid closing the file - * (since this will be the only open object currently). - */ - f->nopen_objs++; - if(H5O_close(&ext_loc) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close superblock extension") - f->nopen_objs--; + /* Close superblock extension */ + if(H5F_super_ext_close(f, &ext_loc) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension") } /* end if */ done: @@ -1008,3 +1127,135 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5F_super_ext_size() */ + +/*------------------------------------------------------------------------- + * Function: H5F_super_ext_write_msg() + * + * Purpose: Write the message with ID to the superblock extension + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi; Feb 2009 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_super_ext_write_msg(H5F_t *f, hid_t dxpl_id, void *mesg, unsigned id, hbool_t may_create) +{ + H5O_loc_t ext_loc; /* "Object location" for superblock extension */ + htri_t status; /* Indicate whether the message exists or not */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_super_ext_write_msg, FAIL) + + /* Sanity checks */ + HDassert(f); + HDassert(f->shared); + HDassert(f->shared->extension_addr); + + /* Open/create the superblock extension object header */ + if(H5F_addr_defined(f->shared->extension_addr)) { + if(H5F_super_ext_open(f, f->shared->extension_addr, &ext_loc) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENOBJ, FAIL, "unable to open file's superblock extension") + } /* end if */ + else { + HDassert(may_create); + if(H5F_super_ext_create(f, dxpl_id, &ext_loc) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "unable to create file's superblock extension") + } /* end else */ + HDassert(H5F_addr_defined(ext_loc.addr)); + + /* Check if message with ID does not exist in the object header */ + if((status = H5O_msg_exists(&ext_loc, id, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to check object header for message or message exists") + + /* Check for creating vs. writing */ + if(may_create) { + if(status) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "Message should not exist") + + /* Create the message with ID in the superblock extension */ + if(H5O_msg_create(&ext_loc, id, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, mesg, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to create the message in object header") + } /* end if */ + else { + if(!status) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "Message should exist") + + /* Update the message with ID in the superblock extension */ + if(H5O_msg_write(&ext_loc, id, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, mesg, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to write the message in object header") + } /* end else */ + + /* Close the superblock extension object header */ + if(H5F_super_ext_close(f, &ext_loc) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F_super_ext_write_msg() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_super_ext_remove_msg + * + * Purpose: Remove the message with ID from the superblock extension + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi; Feb 2009 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_super_ext_remove_msg(H5F_t *f, hid_t dxpl_id, unsigned id) +{ + htri_t status; /* Indicate whether the message exists or not */ + H5O_loc_t ext_loc; /* "Object location" for superblock extension */ + int null_count = 0; /* # of null messages */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_super_ext_remove_msg, FAIL) + + /* Make sure that the superblock extension object header exists */ + HDassert(H5F_addr_defined(f->shared->extension_addr)); + + /* Open superblock extension object header */ + if(H5F_super_ext_open(f, f->shared->extension_addr, &ext_loc) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "error in starting file's superblock extension") + + /* Check if message with ID exists in the object header */ + if((status = H5O_msg_exists(&ext_loc, id, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to check object header for message") + else if(status) { /* message exists */ + H5O_hdr_info_t hdr_info; /* Object header info for superblock extension */ + + /* Remove the message */ + if(H5O_msg_remove(&ext_loc, id, H5O_ALL, TRUE, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete free-space manager info message") + + /* Get info for the superblock extension's object header */ + if(H5O_get_hdr_info(&ext_loc, dxpl_id, &hdr_info) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve superblock extension info") + + /* If the object header is an empty base chunk, remove superblock extension */ + if(hdr_info.nchunks == 1) { + if((null_count = H5O_msg_count(&ext_loc, H5O_NULL_ID, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "unable to count messages") + else if((unsigned)null_count == hdr_info.nmesgs) { + HDassert(H5F_addr_defined(ext_loc.addr)); + if(H5O_delete(f, dxpl_id, ext_loc.addr) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "unable to count messages") + f->shared->extension_addr = HADDR_UNDEF; + } /* end if */ + } /* end if */ + } /* end if */ + + /* Close superblock extension object header */ + if(H5F_super_ext_close(f, &ext_loc) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close file's superblock extension") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F_super_ext_remove_msg() */ + @@ -84,6 +84,7 @@ static herr_t H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type); static herr_t H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id, hid_t dxpl_id); +static herr_t H5O_get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr); /*********************/ @@ -2509,6 +2510,131 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_get_hdr_info + * + * Purpose: Retrieve the object header information for an object + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * September 22 2009 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_get_hdr_info(const H5O_loc_t *loc, hid_t dxpl_id, H5O_hdr_info_t *hdr) +{ + H5O_t *oh = NULL; /* Object header */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_get_hdr_info, FAIL) + + /* Check args */ + HDassert(loc); + HDassert(hdr); + + /* Reset the object header info structure */ + HDmemset(hdr, 0, sizeof(*hdr)); + + /* Get the object header */ + if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") + + /* Get the information for the object header */ + if(H5O_get_hdr_info_real(oh, hdr) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object header info") + +done: + if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_get_hdr_info() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_get_hdr_info_real + * + * Purpose: Internal routine to retrieve the object header information for an object + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * September 22 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr) +{ + const H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ + const H5O_chunk_t *curr_chunk; /* Pointer to current message being operated on */ + unsigned u; /* Local index variable */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_get_hdr_info_real) + + /* Check args */ + HDassert(oh); + HDassert(hdr); + + /* Set the version for the object header */ + hdr->version = oh->version; + + /* Set the number of messages & chunks */ + hdr->nmesgs = oh->nmesgs; + hdr->nchunks = oh->nchunks; + + /* Set the status flags */ + hdr->flags = oh->flags; + + /* Iterate over all the messages, accumulating message size & type information */ + hdr->space.meta = H5O_SIZEOF_HDR(oh) + (H5O_SIZEOF_CHKHDR_OH(oh) * (oh->nchunks - 1)); + hdr->space.mesg = 0; + hdr->space.free = 0; + hdr->mesg.present = 0; + hdr->mesg.shared = 0; + for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { + uint64_t type_flag; /* Flag for message type */ + + /* Accumulate space usage information, based on the type of message */ + if(H5O_NULL_ID == curr_msg->type->id) + hdr->space.free += H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size; + else if(H5O_CONT_ID == curr_msg->type->id) + hdr->space.meta += H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size; + else { + hdr->space.meta += H5O_SIZEOF_MSGHDR_OH(oh); + hdr->space.mesg += curr_msg->raw_size; + } /* end else */ + + /* Set flag to indicate presence of message type */ + type_flag = ((uint64_t)1) << curr_msg->type->id; + hdr->mesg.present |= type_flag; + + /* Set flag if the message is shared in some way */ + if(curr_msg->flags & H5O_MSG_FLAG_SHARED) \ + hdr->mesg.shared |= type_flag; + } /* end for */ + + /* Iterate over all the chunks, adding any gaps to the free space */ + hdr->space.total = 0; + for(u = 0, curr_chunk = &oh->chunk[0]; u < oh->nchunks; u++, curr_chunk++) { + /* Accumulate the size of the header on disk */ + hdr->space.total += curr_chunk->size; + + /* If the chunk has a gap, add it to the free space */ + hdr->space.free += curr_chunk->gap; + } /* end for */ + + /* Sanity check that all the bytes are accounted for */ + HDassert(hdr->space.total == (hdr->space.free + hdr->space.meta + hdr->space.mesg)); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_get_hdr_info_real() */ + + +/*------------------------------------------------------------------------- * Function: H5O_get_info * * Purpose: Retrieve the information for an object @@ -2594,43 +2720,9 @@ H5O_get_info(const H5O_loc_t *loc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info } /* end if */ } /* end else */ - /* Set the version for the object header */ - oinfo->hdr.version = oh->version; - - /* Set the number of messages & chunks */ - oinfo->hdr.nmesgs = oh->nmesgs; - oinfo->hdr.nchunks = oh->nchunks; - - /* Set the status flags */ - oinfo->hdr.flags = oh->flags; - - /* Iterate over all the messages, accumulating message size & type information */ - oinfo->hdr.space.meta = H5O_SIZEOF_HDR(oh) + (H5O_SIZEOF_CHKHDR_OH(oh) * (oh->nchunks - 1)); - oinfo->hdr.space.mesg = 0; - oinfo->hdr.space.free = 0; - oinfo->hdr.mesg.present = 0; - oinfo->hdr.mesg.shared = 0; - for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { - uint64_t type_flag; /* Flag for message type */ - - /* Accumulate space usage information, based on the type of message */ - if(H5O_NULL_ID == curr_msg->type->id) - oinfo->hdr.space.free += H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size; - else if(H5O_CONT_ID == curr_msg->type->id) - oinfo->hdr.space.meta += H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size; - else { - oinfo->hdr.space.meta += H5O_SIZEOF_MSGHDR_OH(oh); - oinfo->hdr.space.mesg += curr_msg->raw_size; - } /* end else */ - - /* Set flag to indicate presence of message type */ - type_flag = ((uint64_t)1) << curr_msg->type->id; - oinfo->hdr.mesg.present |= type_flag; - - /* Set flag if the message is shared in some way */ - if(curr_msg->flags & H5O_MSG_FLAG_SHARED) \ - oinfo->hdr.mesg.shared |= type_flag; - } /* end for */ + /* Get the information for the object header */ + if(H5O_get_hdr_info_real(oh, &oinfo->hdr) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object header info") /* Retrieve # of attributes */ oinfo->num_attrs = H5O_attr_count_real(loc->file, dxpl_id, oh); @@ -2641,19 +2733,6 @@ H5O_get_info(const H5O_loc_t *loc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve attribute btree & heap info") } /* end if */ - /* Iterate over all the chunks, adding any gaps to the free space */ - oinfo->hdr.space.total = 0; - for(u = 0, curr_chunk = &oh->chunk[0]; u < oh->nchunks; u++, curr_chunk++) { - /* Accumulate the size of the header on disk */ - oinfo->hdr.space.total += curr_chunk->size; - - /* If the chunk has a gap, add it to the free space */ - oinfo->hdr.space.free += curr_chunk->gap; - } /* end for */ - - /* Sanity check that all the bytes are accounted for */ - HDassert(oinfo->hdr.space.total == (oinfo->hdr.space.free + oinfo->hdr.space.meta + oinfo->hdr.space.mesg)); - done: if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header") diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index e0364c7..551f7b8 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -559,6 +559,7 @@ H5_DLL herr_t H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_DLL herr_t H5O_bogus_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned mesg_flags); #endif /* H5O_ENABLE_BOGUS */ H5_DLL herr_t H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr); +H5_DLL herr_t H5O_get_hdr_info(const H5O_loc_t *oloc, hid_t dxpl_id, H5O_hdr_info_t *hdr); H5_DLL herr_t H5O_get_info(const H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *oinfo); H5_DLL herr_t H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type, hid_t dxpl_id); diff --git a/src/H5Opublic.h b/src/H5Opublic.h index ddf1a93..84fdecc 100644 --- a/src/H5Opublic.h +++ b/src/H5Opublic.h @@ -87,6 +87,24 @@ typedef enum H5O_type_t { H5O_TYPE_NTYPES /* Number of different object types (must be last!) */ } H5O_type_t; +/* Information struct for object header metadata (for H5Oget_info/H5Oget_info_by_name/H5Oget_info_by_idx) */ +typedef struct H5O_hdr_info_t { + unsigned version; /* Version number of header format in file */ + unsigned nmesgs; /* Number of object header messages */ + unsigned nchunks; /* Number of object header chunks */ + unsigned flags; /* Object header status flags */ + struct { + hsize_t total; /* Total space for storing object header in file */ + hsize_t meta; /* Space within header for object header metadata information */ + hsize_t mesg; /* Space within header for actual message information */ + hsize_t free; /* Free space within object header */ + } space; + struct { + uint64_t present; /* Flags to indicate presence of message type in header */ + uint64_t shared; /* Flags to indicate message type is shared in header */ + } mesg; +} H5O_hdr_info_t; + /* Information struct for object (for H5Oget_info/H5Oget_info_by_name/H5Oget_info_by_idx) */ typedef struct H5O_info_t { unsigned long fileno; /* File number that object is located in */ @@ -98,22 +116,7 @@ typedef struct H5O_info_t { time_t ctime; /* Change time */ time_t btime; /* Birth time */ hsize_t num_attrs; /* # of attributes attached to object */ - struct { - unsigned version; /* Version number of header format in file */ - unsigned nmesgs; /* Number of object header messages */ - unsigned nchunks; /* Number of object header chunks */ - unsigned flags; /* Object header status flags */ - struct { - hsize_t total; /* Total space for storing object header in file */ - hsize_t meta; /* Space within header for object header metadata information */ - hsize_t mesg; /* Space within header for actual message information */ - hsize_t free; /* Free space within object header */ - } space; - struct { - uint64_t present; /* Flags to indicate presence of message type in header */ - uint64_t shared; /* Flags to indicate message type is shared in header */ - } mesg; - } hdr; + H5O_hdr_info_t hdr; /* Object header information */ /* Extra metadata storage for obj & attributes */ struct { H5_ih_info_t obj; /* v1/v2 B-tree & local/fractal heap for groups, B-tree for chunked datasets */ |