summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2010-07-22 17:04:48 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2010-07-22 17:04:48 (GMT)
commit2ae193a0383a75c365c1cb2116428dc173c1610d (patch)
treee2e84fb762d9946a91b4a288ca6835688864087c
parent87748c6a0b5d3aba7cfce54746ebae2f5caeebc6 (diff)
downloadhdf5-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.c2
-rw-r--r--src/H5C.c5
-rw-r--r--src/H5Eint.c101
-rw-r--r--src/H5Eprivate.h41
-rw-r--r--src/H5Fpkg.h5
-rw-r--r--src/H5Fsuper.c303
-rw-r--r--src/H5O.c179
-rw-r--r--src/H5Oprivate.h1
-rw-r--r--src/H5Opublic.h35
9 files changed, 552 insertions, 120 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index fd2df15..48b6635 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -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 ) ) {
diff --git a/src/H5C.c b/src/H5C.c
index cedc461..f60e0f6 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -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() */
+
diff --git a/src/H5O.c b/src/H5O.c
index 86997fe..e22f36f 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -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 */