summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2010-04-15 19:57:02 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2010-04-15 19:57:02 (GMT)
commitebd22f7643d53b234b43393d8ede23e0549caa5f (patch)
tree62b13c6ef0f705822fd925687073df7988bd8288 /src
parent227a351e4758ffb0af9882b00831ad6cf1acff3b (diff)
downloadhdf5-ebd22f7643d53b234b43393d8ede23e0549caa5f.zip
hdf5-ebd22f7643d53b234b43393d8ede23e0549caa5f.tar.gz
hdf5-ebd22f7643d53b234b43393d8ede23e0549caa5f.tar.bz2
[svn-r18571] Description:
Bring r18542 from metadata journaling "merging" branch to trunk: Bring new object header pin/unpin & protect/unprotect routines and split-out object header chunk proxy changes from metadata_journaling branch to "merging" branch, along with some other minor tweaks to clean up compiler warnings, etc. Also: clean up chunk protect/unprotect calls when allocating or freeing space in a chunk, optimize metadata accumulator code to avoid some re-reading of information from the file, refactor H5O_pin/H5O_unpin from way they are done on the merging branch back to way they were previously done on trunk, other minor code cleanups, etc. Tested on FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, 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, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in debug mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode Mac OS X/32 10.6.3 (amazon) in debug mode Mac OS X/32 10.6.3 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode
Diffstat (limited to 'src')
-rw-r--r--src/H5AC.c5
-rw-r--r--src/H5ACprivate.h1
-rw-r--r--src/H5C.c3
-rw-r--r--src/H5Cpkg.h228
-rw-r--r--src/H5Dint.c5
-rw-r--r--src/H5Doh.c2
-rw-r--r--src/H5FL.c2
-rw-r--r--src/H5Faccum.c121
-rw-r--r--src/H5Ffake.c4
-rw-r--r--src/H5Fsfile.c2
-rw-r--r--src/H5G.c7
-rw-r--r--src/H5Gobj.c2
-rw-r--r--src/H5O.c509
-rw-r--r--src/H5Oalloc.c649
-rw-r--r--src/H5Oattribute.c143
-rw-r--r--src/H5Ocache.c1313
-rw-r--r--src/H5Ochunk.c359
-rw-r--r--src/H5Ocont.c9
-rw-r--r--src/H5Ocopy.c5
-rw-r--r--src/H5Odbg.c14
-rw-r--r--src/H5Omessage.c87
-rw-r--r--src/H5Opkg.h72
-rw-r--r--src/H5Oprivate.h7
-rw-r--r--src/H5Oshared.c6
-rw-r--r--src/H5Otest.c81
-rw-r--r--src/H5R.c22
-rwxr-xr-xsrc/H5SM.c5
-rwxr-xr-xsrc/Makefile.am2
-rw-r--r--src/Makefile.in5
29 files changed, 2606 insertions, 1064 deletions
diff --git a/src/H5AC.c b/src/H5AC.c
index ccb5d6e..29b18f5 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -154,7 +154,7 @@ static herr_t H5AC_log_deleted_entry(H5AC_t * cache_ptr,
haddr_t addr,
unsigned int flags);
-static herr_t H5AC_log_dirtied_entry(const H5C_cache_entry_t *entry_ptr,
+static herr_t H5AC_log_dirtied_entry(const H5AC_info_t * entry_ptr,
haddr_t addr,
hbool_t size_changed,
size_t new_size);
@@ -482,6 +482,7 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] =
"local heap data blocks",
"global heaps",
"object headers",
+ "object header chunks",
"v2 B-tree headers",
"v2 B-tree internal nodes",
"v2 B-tree leaf nodes",
@@ -2821,7 +2822,6 @@ herr_t
H5AC_validate_config(H5AC_cache_config_t * config_ptr)
{
herr_t result;
- int name_len;
H5C_auto_size_ctl_t internal_config;
herr_t ret_value = SUCCEED; /* Return value */
@@ -2860,6 +2860,7 @@ H5AC_validate_config(H5AC_cache_config_t * config_ptr)
/* don't bother to test trace_file_name unless open_trace_file is TRUE */
if ( config_ptr->open_trace_file ) {
+ size_t name_len;
/* Can't really test the trace_file_name field without trying to
* open the file, so we will content ourselves with a couple of
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index 05d1904..f9afa3d 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -49,6 +49,7 @@ typedef enum {
H5AC_LHEAP_DBLK_ID, /*local heap data block */
H5AC_GHEAP_ID, /*global heap */
H5AC_OHDR_ID, /*object header */
+ H5AC_OHDR_CHK_ID, /*object header chunk */
H5AC_BT2_HDR_ID, /*v2 B-tree header */
H5AC_BT2_INT_ID, /*v2 B-tree internal node */
H5AC_BT2_LEAF_ID, /*v2 B-tree leaf node */
diff --git a/src/H5C.c b/src/H5C.c
index 5479099..7f15026 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -620,8 +620,7 @@ done:
H5SL_close(cache_ptr->slist_ptr);
cache_ptr->magic = 0;
- (void)H5FL_FREE(H5C_t, cache_ptr);
- cache_ptr = NULL;
+ cache_ptr = H5FL_FREE(H5C_t, cache_ptr);
} /* end if */
diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h
index e7db92b..538bc61 100644
--- a/src/H5Cpkg.h
+++ b/src/H5Cpkg.h
@@ -96,11 +96,11 @@
*
* JRM - 9/26/05
*
- * magic: Unsigned 32 bit integer always set to H5C__H5C_T_MAGIC.
- * This field is used to validate pointers to instances of
+ * magic: Unsigned 32 bit integer always set to H5C__H5C_T_MAGIC.
+ * This field is used to validate pointers to instances of
* H5C_t.
*
- * flush_in_progress: Boolean flag indicating whether a flush is in
+ * flush_in_progress: Boolean flag indicating whether a flush is in
* progress.
*
* trace_file_ptr: File pointer pointing to the trace file, which is used
@@ -109,7 +109,7 @@
* no trace file should be recorded.
*
* Since much of the code supporting the parallel metadata
- * cache is in H5AC, we don't write the trace file from
+ * cache is in H5AC, we don't write the trace file from
* H5C. Instead, H5AC reads the trace_file_ptr as needed.
*
* When we get to using H5C in other places, we may add
@@ -182,7 +182,7 @@
* writes. The following field is used to implement this.
*
* evictions_enabled: Boolean flag that is initialized to TRUE. When
- * this flag is set to FALSE, the metadata cache will not
+ * this flag is set to FALSE, the metadata cache will not
* attempt to evict entries to make space for newly protected
* entries, and instead the will grow without limit.
*
@@ -288,7 +288,7 @@
* following two fields have been added. They are only compiled in when
* H5C_DO_SANITY_CHECKS is TRUE.
*
- * slist_len_increase: Number of entries that have been added to the
+ * slist_len_increase: Number of entries that have been added to the
* slist since the last time this field was set to zero.
*
* slist_size_increase: Total size of all entries that have been added
@@ -625,23 +625,23 @@
* equal to the array index has not been in cache when
* requested in the current epoch.
*
- * write_protects: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The
- * cells are used to record the number of times an entry with
- * type id equal to the array index has been write protected
+ * write_protects: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The
+ * cells are used to record the number of times an entry with
+ * type id equal to the array index has been write protected
* in the current epoch.
*
* Observe that (hits + misses) = (write_protects + read_protects).
*
- * read_protects: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The
- * cells are used to record the number of times an entry with
- * type id equal to the array index has been read protected in
+ * read_protects: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The
+ * cells are used to record the number of times an entry with
+ * type id equal to the array index has been read protected in
* the current epoch.
*
* Observe that (hits + misses) = (write_protects + read_protects).
*
- * max_read_protects: Array of int32 of length H5C__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to maximum number of simultaneous read
- * protects on any entry with type id equal to the array index
+ * max_read_protects: Array of int32 of length H5C__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to maximum number of simultaneous read
+ * protects on any entry with type id equal to the array index
* in the current epoch.
*
* insertions: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The cells
@@ -649,9 +649,9 @@
* id equal to the array index has been inserted into the
* cache in the current epoch.
*
- * pinned_insertions: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to record the number of times an entry
- * with type id equal to the array index has been inserted
+ * pinned_insertions: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to record the number of times an entry
+ * with type id equal to the array index has been inserted
* pinned into the cache in the current epoch.
*
* clears: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The cells
@@ -674,13 +674,13 @@
* id equal to the array index has been renamed in the current
* epoch.
*
- * entry_flush_renames: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to record the number of times an entry
+ * entry_flush_renames: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to record the number of times an entry
* with type id equal to the array index has been renamed
* during its flush callback in the current epoch.
*
- * cache_flush_renames: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to record the number of times an entry
+ * cache_flush_renames: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to record the number of times an entry
* with type id equal to the array index has been renamed
* during a cache flush in the current epoch.
*
@@ -719,14 +719,14 @@
* with type id equal to the array index has decreased in
* size in the current epoch.
*
- * entry_flush_size_changes: Array of int64 of length
- * H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record
- * the number of times an entry with type id equal to the
+ * entry_flush_size_changes: Array of int64 of length
+ * H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record
+ * the number of times an entry with type id equal to the
* array index has changed size while in its flush callback.
*
- * cache_flush_size_changes: Array of int64 of length
- * H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record
- * the number of times an entry with type id equal to the
+ * cache_flush_size_changes: Array of int64 of length
+ * H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record
+ * the number of times an entry with type id equal to the
* array index has changed size during a cache flush
*
* total_ht_insertions: Number of times entries have been inserted into the
@@ -860,7 +860,7 @@
#define H5C__HASH_TABLE_LEN (64 * 1024) /* must be a power of 2 */
#define H5C__H5C_T_MAGIC 0x005CAC0E
-#define H5C__MAX_NUM_TYPE_IDS 26
+#define H5C__MAX_NUM_TYPE_IDS 27
#define H5C__PREFIX_LEN 32
struct H5C_t
@@ -1449,7 +1449,7 @@ if ( ( (entry_ptr) == NULL ) || \
* More pinned entry stats related updates.
*
* JRM -- 3/31/07
- * Updated H5C__UPDATE_STATS_FOR_PROTECT() to keep stats on
+ * Updated H5C__UPDATE_STATS_FOR_PROTECT() to keep stats on
* read and write protects.
*
* MAM -- 1/15/09
@@ -2877,7 +2877,7 @@ if ( (cache_ptr)->index_size != \
(cache_ptr)->pel_tail_ptr, \
(cache_ptr)->pel_len, \
(cache_ptr)->pel_size, (fail_val)) \
- \
+ \
} else { \
\
/* modified LRU specific code */ \
@@ -3122,62 +3122,70 @@ if ( (cache_ptr)->index_size != \
HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \
HDassert( (entry_ptr)->size > 0 ); \
\
- if ( ! ((entry_ptr)->is_pinned) ) { \
- \
+ if ( ! ( (entry_ptr)->is_pinned ) ) { \
+ \
/* modified LRU specific code */ \
\
/* remove the entry from the LRU list, and re-insert it at the head. \
*/ \
\
- H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
- (cache_ptr)->LRU_tail_ptr, \
- (cache_ptr)->LRU_list_len, \
- (cache_ptr)->LRU_list_size, (fail_val)) \
+ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ (cache_ptr)->LRU_tail_ptr, \
+ (cache_ptr)->LRU_list_len, \
+ (cache_ptr)->LRU_list_size, (fail_val)) \
\
H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
(cache_ptr)->LRU_tail_ptr, \
(cache_ptr)->LRU_list_len, \
(cache_ptr)->LRU_list_size, (fail_val)) \
\
- /* remove the entry from either the clean or dirty LUR list as \
- * indicated by the was_dirty parameter \
- */ \
- if ( was_dirty ) { \
+ /* remove the entry from either the clean or dirty LUR list as \
+ * indicated by the was_dirty parameter \
+ */ \
+ if ( was_dirty ) { \
\
- H5C__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \
- (cache_ptr)->dLRU_tail_ptr, \
- (cache_ptr)->dLRU_list_len, \
- (cache_ptr)->dLRU_list_size, (fail_val)) \
+ H5C__AUX_DLL_REMOVE((entry_ptr), \
+ (cache_ptr)->dLRU_head_ptr, \
+ (cache_ptr)->dLRU_tail_ptr, \
+ (cache_ptr)->dLRU_list_len, \
+ (cache_ptr)->dLRU_list_size, \
+ (fail_val)) \
\
- } else { \
+ } else { \
\
- H5C__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \
- (cache_ptr)->cLRU_tail_ptr, \
- (cache_ptr)->cLRU_list_len, \
- (cache_ptr)->cLRU_list_size, (fail_val)) \
- } \
+ H5C__AUX_DLL_REMOVE((entry_ptr), \
+ (cache_ptr)->cLRU_head_ptr, \
+ (cache_ptr)->cLRU_tail_ptr, \
+ (cache_ptr)->cLRU_list_len, \
+ (cache_ptr)->cLRU_list_size, \
+ (fail_val)) \
+ } \
\
- /* insert the entry at the head of either the clean or dirty LRU \
- * list as appropriate. \
- */ \
+ /* insert the entry at the head of either the clean or dirty \
+ * LRU list as appropriate. \
+ */ \
\
- if ( (entry_ptr)->is_dirty ) { \
+ if ( (entry_ptr)->is_dirty ) { \
\
- H5C__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \
- (cache_ptr)->dLRU_tail_ptr, \
- (cache_ptr)->dLRU_list_len, \
- (cache_ptr)->dLRU_list_size, (fail_val)) \
+ H5C__AUX_DLL_PREPEND((entry_ptr), \
+ (cache_ptr)->dLRU_head_ptr, \
+ (cache_ptr)->dLRU_tail_ptr, \
+ (cache_ptr)->dLRU_list_len, \
+ (cache_ptr)->dLRU_list_size, \
+ (fail_val)) \
\
- } else { \
+ } else { \
\
- H5C__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \
- (cache_ptr)->cLRU_tail_ptr, \
- (cache_ptr)->cLRU_list_len, \
- (cache_ptr)->cLRU_list_size, (fail_val)) \
- } \
+ H5C__AUX_DLL_PREPEND((entry_ptr), \
+ (cache_ptr)->cLRU_head_ptr, \
+ (cache_ptr)->cLRU_tail_ptr, \
+ (cache_ptr)->cLRU_list_len, \
+ (cache_ptr)->cLRU_list_size, \
+ (fail_val)) \
+ } \
\
- /* End modified LRU specific code. */ \
- } \
+ /* End modified LRU specific code. */ \
+ } \
} /* H5C__UPDATE_RP_FOR_RENAME */
#else /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
@@ -3192,25 +3200,25 @@ if ( (cache_ptr)->index_size != \
HDassert( ((entry_ptr)->ro_ref_count) == 0 ); \
HDassert( (entry_ptr)->size > 0 ); \
\
- if ( ! ((entry_ptr)->is_pinned) ) { \
- \
+ if ( ! ( (entry_ptr)->is_pinned ) ) { \
+ \
/* modified LRU specific code */ \
\
/* remove the entry from the LRU list, and re-insert it at the head. \
*/ \
\
- H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
- (cache_ptr)->LRU_tail_ptr, \
- (cache_ptr)->LRU_list_len, \
- (cache_ptr)->LRU_list_size, (fail_val)) \
+ H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ (cache_ptr)->LRU_tail_ptr, \
+ (cache_ptr)->LRU_list_len, \
+ (cache_ptr)->LRU_list_size, (fail_val)) \
\
- H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
- (cache_ptr)->LRU_tail_ptr, \
- (cache_ptr)->LRU_list_len, \
- (cache_ptr)->LRU_list_size, (fail_val)) \
+ H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ (cache_ptr)->LRU_tail_ptr, \
+ (cache_ptr)->LRU_list_len, \
+ (cache_ptr)->LRU_list_size, (fail_val)) \
\
- /* End modified LRU specific code. */ \
- } \
+ /* End modified LRU specific code. */ \
+ } \
} /* H5C__UPDATE_RP_FOR_RENAME */
#endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
@@ -3267,7 +3275,7 @@ if ( (cache_ptr)->index_size != \
(cache_ptr)->pel_size, \
(entry_ptr)->size, \
(new_size)); \
- \
+ \
} else { \
\
/* modified LRU specific code */ \
@@ -3393,35 +3401,39 @@ if ( (cache_ptr)->index_size != \
(cache_ptr)->pel_size, (fail_val)) \
HDassert( (cache_ptr)->pel_len >= 0 ); \
\
- /* modified LRU specific code */ \
+ /* modified LRU specific code */ \
\
- /* insert the entry at the head of the LRU list. */ \
+ /* insert the entry at the head of the LRU list. */ \
\
- H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
- (cache_ptr)->LRU_tail_ptr, \
- (cache_ptr)->LRU_list_len, \
- (cache_ptr)->LRU_list_size, (fail_val)) \
+ H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ (cache_ptr)->LRU_tail_ptr, \
+ (cache_ptr)->LRU_list_len, \
+ (cache_ptr)->LRU_list_size, (fail_val)) \
\
- /* Similarly, insert the entry at the head of either the clean or \
- * dirty LRU list as appropriate. \
- */ \
+ /* Similarly, insert the entry at the head of either the clean \
+ * or dirty LRU list as appropriate. \
+ */ \
\
- if ( (entry_ptr)->is_dirty ) { \
+ if ( (entry_ptr)->is_dirty ) { \
\
- H5C__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \
- (cache_ptr)->dLRU_tail_ptr, \
- (cache_ptr)->dLRU_list_len, \
- (cache_ptr)->dLRU_list_size, (fail_val)) \
+ H5C__AUX_DLL_PREPEND((entry_ptr), \
+ (cache_ptr)->dLRU_head_ptr, \
+ (cache_ptr)->dLRU_tail_ptr, \
+ (cache_ptr)->dLRU_list_len, \
+ (cache_ptr)->dLRU_list_size, \
+ (fail_val)) \
\
- } else { \
+ } else { \
\
- H5C__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \
- (cache_ptr)->cLRU_tail_ptr, \
- (cache_ptr)->cLRU_list_len, \
- (cache_ptr)->cLRU_list_size, (fail_val)) \
- } \
+ H5C__AUX_DLL_PREPEND((entry_ptr), \
+ (cache_ptr)->cLRU_head_ptr, \
+ (cache_ptr)->cLRU_tail_ptr, \
+ (cache_ptr)->cLRU_list_len, \
+ (cache_ptr)->cLRU_list_size, \
+ (fail_val)) \
+ } \
\
- /* End modified LRU specific code. */ \
+ /* End modified LRU specific code. */ \
\
} /* H5C__UPDATE_RP_FOR_UNPIN */
@@ -3446,16 +3458,16 @@ if ( (cache_ptr)->index_size != \
(cache_ptr)->pel_size, (fail_val)) \
HDassert( (cache_ptr)->pel_len >= 0 ); \
\
- /* modified LRU specific code */ \
+ /* modified LRU specific code */ \
\
- /* insert the entry at the head of the LRU list. */ \
+ /* insert the entry at the head of the LRU list. */ \
\
- H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
- (cache_ptr)->LRU_tail_ptr, \
- (cache_ptr)->LRU_list_len, \
- (cache_ptr)->LRU_list_size, (fail_val)) \
+ H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \
+ (cache_ptr)->LRU_tail_ptr, \
+ (cache_ptr)->LRU_list_len, \
+ (cache_ptr)->LRU_list_size, (fail_val)) \
\
- /* End modified LRU specific code. */ \
+ /* End modified LRU specific code. */ \
\
} /* H5C__UPDATE_RP_FOR_UNPIN */
diff --git a/src/H5Dint.c b/src/H5Dint.c
index d3800e8..72c9079 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -27,7 +27,6 @@
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
#include "H5Dpkg.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
@@ -794,7 +793,7 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, hid_t dapl_id)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset object header")
HDassert(file == dset->oloc.file);
- /* Get a pointer to the object header itself */
+ /* Pin the object header */
if(NULL == (oh = H5O_pin(oloc, dxpl_id)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header")
@@ -2261,7 +2260,7 @@ H5D_flush_real(H5D_t *dataset, hid_t dxpl_id)
if(dataset->shared->layout_dirty || dataset->shared->space_dirty) {
unsigned update_flags = H5O_UPDATE_TIME; /* Modification time flag */
- /* Get a pointer to the dataset's object header */
+ /* Pin the object header */
if(NULL == (oh = H5O_pin(&dataset->oloc, dxpl_id)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header")
diff --git a/src/H5Doh.c b/src/H5Doh.c
index 8ed6644..e600853 100644
--- a/src/H5Doh.c
+++ b/src/H5Doh.c
@@ -159,7 +159,7 @@ H5O_dset_free_copy_file_udata(void *_udata)
H5O_msg_free(H5O_PLINE_ID, udata->common.src_pline);
/* Release space for 'copy file' user data */
- (void)H5FL_FREE(H5D_copy_file_ud_t, udata);
+ udata = H5FL_FREE(H5D_copy_file_ud_t, udata);
FUNC_LEAVE_NOAPI_VOID
} /* end H5O_dset_free_copy_file_udata() */
diff --git a/src/H5FL.c b/src/H5FL.c
index 8ac442a..2f5c2e1 100644
--- a/src/H5FL.c
+++ b/src/H5FL.c
@@ -2352,7 +2352,7 @@ H5FL_fac_term(H5FL_fac_head_t *factory)
} /* end else */
/* Free factory info */
- (void)H5FL_FREE(H5FL_fac_head_t, factory);
+ factory = H5FL_FREE(H5FL_fac_head_t, factory);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Faccum.c b/src/H5Faccum.c
index e525a08..426a639 100644
--- a/src/H5Faccum.c
+++ b/src/H5Faccum.c
@@ -126,68 +126,68 @@ H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
/* Check if this information is in the metadata accumulator */
if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW
&& size < H5F_ACCUM_MAX_SIZE) {
- /* Current read overlaps with metadata accumulator */
- if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
- unsigned char *read_buf = (unsigned char *)buf; /* Pointer to the buffer being read in */
- size_t amount_read; /* Amount to read at a time */
- hsize_t read_off; /* Offset to read from */
+ /* Sanity check */
+ HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size));
+
+ /* Current read adjoins or overlaps with metadata accumulator */
+ if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)
+ || ((addr + size) == f->shared->accum.loc)
+ || (f->shared->accum.loc + f->shared->accum.size) == addr) {
+ size_t amount_before; /* Amount to read before current accumulator */
+ haddr_t new_addr; /* New address of the accumulator buffer */
+ size_t new_size; /* New size of the accumulator buffer */
+
+ /* Compute new values for accumulator */
+ new_addr = MIN(addr, f->shared->accum.loc);
+ new_size = (size_t)(MAX((addr + size), (f->shared->accum.loc + f->shared->accum.size))
+ - new_addr);
+
+ /* Check if we need more buffer space */
+ if(new_size > f->shared->accum.size) {
+ /* Adjust the buffer size, by doubling it */
+ f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, new_size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
/* Read the part before the metadata accumulator */
if(addr < f->shared->accum.loc) {
/* Set the amount to read */
- H5_ASSIGN_OVERFLOW(amount_read, (f->shared->accum.loc - addr), hsize_t, size_t);
+ H5_ASSIGN_OVERFLOW(amount_before, (f->shared->accum.loc - addr), hsize_t, size_t);
+
+ /* Make room for the metadata to read in */
+ HDmemmove(f->shared->accum.buf + amount_before, f->shared->accum.buf, f->shared->accum.size);
/* Dispatch to driver */
- if(H5FD_read(f->shared->lf, dxpl_id, type, addr, amount_read, read_buf) < 0)
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, amount_before, f->shared->accum.buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
-
- /* Adjust the buffer, address & size */
- read_buf += amount_read;
- addr += amount_read;
- size -= amount_read;
} /* end if */
+ else
+ amount_before = 0;
- /* Copy the part overlapping the metadata accumulator */
- if(size > 0 && (addr >= f->shared->accum.loc && addr < (f->shared->accum.loc + f->shared->accum.size))) {
- /* Set the offset to "read" from */
- read_off = addr - f->shared->accum.loc;
-
- /* Set the amount to "read" */
-#ifndef NDEBUG
-{
- hsize_t tempamount_read; /* Amount to read at a time */
-
- tempamount_read = f->shared->accum.size - read_off;
- H5_CHECK_OVERFLOW(tempamount_read, hsize_t, size_t);
- amount_read = MIN(size, (size_t)tempamount_read);
-}
-#else /* NDEBUG */
- amount_read = MIN(size, (size_t)(f->shared->accum.size - read_off));
-#endif /* NDEBUG */
-
- /* Copy the data out of the buffer */
- HDmemcpy(read_buf, f->shared->accum.buf + read_off, amount_read);
+ /* Read the part after the metadata accumulator */
+ if((addr + size) > (f->shared->accum.loc + f->shared->accum.size)) {
+ size_t amount_after; /* Amount to read at a time */
- /* Adjust the buffer, address & size */
- read_buf += amount_read;
- addr += amount_read;
- size -= amount_read;
- } /* end if */
+ /* Set the amount to read */
+ H5_ASSIGN_OVERFLOW(amount_after, ((addr + size) - (f->shared->accum.loc + f->shared->accum.size)), hsize_t, size_t);
- /* Read the part after the metadata accumulator */
- if(size > 0 && addr >= (f->shared->accum.loc + f->shared->accum.size)) {
/* Dispatch to driver */
- if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, read_buf) < 0)
+ if(H5FD_read(f->shared->lf, dxpl_id, type, (f->shared->accum.loc + f->shared->accum.size), amount_after, (f->shared->accum.buf + f->shared->accum.size + amount_before)) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
-
- /* Adjust the buffer, address & size */
- read_buf += size;
- addr += size;
- size -= size;
} /* end if */
- /* Make certain we've read it all */
- HDassert(size == 0);
+ /* Copy the data out of the buffer */
+ HDmemcpy(buf, f->shared->accum.buf + (addr - new_addr), size);
+
+ /* Adjust the accumulator address & size */
+ f->shared->accum.loc = new_addr;
+ f->shared->accum.size = new_size;
} /* end if */
/* Current read doesn't overlap with metadata accumulator, read it from file */
else {
@@ -340,6 +340,9 @@ H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
/* Check for accumulating metadata */
if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW
&& size < H5F_ACCUM_MAX_SIZE) {
+ /* Sanity check */
+ HDassert(!f->shared->accum.buf || (f->shared->accum.alloc_size >= f->shared->accum.size));
+
/* Check if there is already metadata in the accumulator */
if(f->shared->accum.size > 0) {
/* Check if the new metadata adjoins the beginning of the current accumulator */
@@ -433,8 +436,30 @@ H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
/* Mark it as written to */
f->shared->accum.dirty = TRUE;
} /* end if */
+ /* New metadata overlaps both ends of the current accumulator */
else {
- HDassert(0 && "New metadata overlapped both beginning and end of existing metadata accumulator!");
+ /* Check if we need more buffer space */
+ if(size > f->shared->accum.size) {
+ /* Adjust the buffer size, by doubling it */
+ f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + size, 0, (f->shared->accum.alloc_size - size));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Copy the new metadata to the buffer */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size = size;
+
+ /* Mark it as written to */
+ f->shared->accum.dirty = TRUE;
} /* end else */
} /* end if */
/* New piece of metadata doesn't adjoin or overlap the existing accumulator */
diff --git a/src/H5Ffake.c b/src/H5Ffake.c
index e96aedf..f71d373 100644
--- a/src/H5Ffake.c
+++ b/src/H5Ffake.c
@@ -120,8 +120,8 @@ H5F_fake_free(H5F_t *f)
if(f) {
/* Destroy shared file struct */
if(f->shared)
- f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared);
- (void)H5FL_FREE(H5F_t, f);
+ f->shared = H5FL_FREE(H5F_file_t, f->shared);
+ f = H5FL_FREE(H5F_t, f);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
diff --git a/src/H5Fsfile.c b/src/H5Fsfile.c
index 708fbf7..8144986 100644
--- a/src/H5Fsfile.c
+++ b/src/H5Fsfile.c
@@ -219,7 +219,7 @@ H5F_sfile_remove(H5F_file_t *shared)
/* Release the shared file node struct */
/* (the shared file info itself is freed elsewhere) */
- (void)H5FL_FREE(H5F_sfile_node_t, curr);
+ curr = H5FL_FREE(H5F_sfile_node_t, curr);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5G.c b/src/H5G.c
index 204245a..de501ea 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -1772,8 +1772,7 @@ H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type,
H5G_t *grp = NULL; /* Group opened */
H5G_loc_t loc; /* Location of group passed in */
H5G_loc_t start_loc; /* Location of starting group */
- H5O_type_t otype; /* Basic object type (group, dataset, etc.) */
- unsigned rc; /* Reference count of object */
+ unsigned rc; /* Reference count of object */
herr_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_visit, FAIL)
@@ -1814,8 +1813,8 @@ H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type,
if((udata.visited = H5SL_create(H5SL_TYPE_OBJ)) == NULL)
HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects")
- /* Get the group's reference count and type */
- if(H5O_get_rc_and_type(&grp->oloc, dxpl_id, &rc, &otype) < 0)
+ /* Get the group's reference count */
+ if(H5O_get_rc_and_type(&grp->oloc, dxpl_id, &rc, NULL) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get object info")
/* If its ref count is > 1, we add it to the list of visited objects */
diff --git a/src/H5Gobj.c b/src/H5Gobj.c
index 7766280..daad6ae 100644
--- a/src/H5Gobj.c
+++ b/src/H5Gobj.c
@@ -901,7 +901,7 @@ H5G_obj_remove_update_linfo(H5O_loc_t *oloc, H5O_linfo_t *linfo, hid_t dxpl_id)
if(H5G_dense_build_table(oloc->file, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, &ltable) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links")
- /* Get a pointer to the object header itself */
+ /* Pin the object header */
if(NULL == (oh = H5O_pin(oloc, dxpl_id)))
HGOTO_ERROR(H5E_SYM, H5E_CANTPIN, FAIL, "unable to pin group object header")
diff --git a/src/H5O.c b/src/H5O.c
index 87b86ab..5abf7d9 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -141,6 +141,9 @@ H5FL_SEQ_DEFINE(H5O_chunk_t);
/* Declare a free list to manage the chunk image information */
H5FL_BLK_DEFINE(chunk_image);
+/* Declare external the free list for H5O_cont_t sequences */
+H5FL_SEQ_EXTERN(H5O_cont_t);
+
/*****************************/
/* Library Private Variables */
@@ -1173,7 +1176,7 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
/* Determine correct value for chunk #0 size bits */
/* Avoid compiler warning on 32-bit machines */
#if H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T
- if(size_hint > 4294967295)
+ if(size_hint > 4294967295UL)
oh->flags |= H5O_HDR_CHUNK0_8;
else
#endif /* H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T */
@@ -1189,7 +1192,7 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
/* Compute total size of initial object header */
/* (i.e. object header prefix and first chunk) */
- oh_size = H5O_SIZEOF_HDR(oh) + size_hint;
+ oh_size = (size_t)H5O_SIZEOF_HDR(oh) + size_hint;
/* Allocate disk space for header and first chunk */
if(HADDR_UNDEF == (oh_addr = H5MF_alloc(f, H5FD_MEM_OHDR, dxpl_id, (hsize_t)oh_size)))
@@ -1201,7 +1204,6 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Initialize the first chunk */
- oh->chunk[0].dirty = TRUE;
oh->chunk[0].addr = oh_addr;
oh->chunk[0].size = oh_size;
oh->chunk[0].gap = 0;
@@ -1457,13 +1459,18 @@ done:
*-------------------------------------------------------------------------
*/
int
-H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags)
+H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, hbool_t *deleted)
{
haddr_t addr = H5O_OH_GET_ADDR(oh); /* Object header address */
int ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5O_link_oh, FAIL)
+ /* check args */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(deleted);
+
/* Check for adjusting link count */
if(adjust) {
if(adjust < 0) {
@@ -1475,7 +1482,8 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags)
oh->nlink += adjust;
/* Mark object header as dirty in cache */
- *oh_flags |= H5AC__DIRTIED_FLAG;
+ if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
/* Check if the object should be deleted */
if(oh->nlink == 0) {
@@ -1486,12 +1494,8 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion")
} /* end if */
else {
- /* Delete object right now */
- if(H5O_delete_oh(f, dxpl_id, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
-
/* Mark the object header for deletion */
- *oh_flags = H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
+ *deleted = TRUE;
} /* end else */
} /* end if */
} /* end if */
@@ -1510,7 +1514,8 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags)
oh->nlink += adjust;
/* Mark object header as dirty in cache */
- *oh_flags |= H5AC__DIRTIED_FLAG;
+ if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
} /* end if */
/* Check for operations on refcount message */
@@ -1520,7 +1525,7 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags)
/* Check for removing refcount message */
if(oh->nlink <= 1) {
if(H5O_msg_remove_real(f, oh, H5O_MSG_REFCOUNT, H5O_ALL, NULL, NULL, TRUE, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete refcount message")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete refcount message")
oh->has_refcount_msg = FALSE;
} /* end if */
/* Update refcount message with new link count */
@@ -1528,7 +1533,7 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags)
H5O_refcount_t refcount = oh->nlink;
if(H5O_msg_write_real(f, dxpl_id, oh, H5O_MSG_REFCOUNT, H5O_MSG_FLAG_DONTSHARE, 0, &refcount) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update refcount message")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update refcount message")
} /* end else */
} /* end if */
else {
@@ -1537,7 +1542,7 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags)
H5O_refcount_t refcount = oh->nlink;
if(H5O_msg_append_real(f, dxpl_id, oh, H5O_MSG_REFCOUNT, H5O_MSG_FLAG_DONTSHARE, 0, &refcount) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new refcount message")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to create new refcount message")
oh->has_refcount_msg = TRUE;
} /* end if */
} /* end else */
@@ -1548,7 +1553,7 @@ H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags)
ret_value = (int)oh->nlink;
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_link_oh() */
@@ -1572,9 +1577,8 @@ int
H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id)
{
H5O_t *oh = NULL;
- H5AC_protect_t oh_acc; /* Access mode for protecting object header */
- unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Whether the object was deleted */
- int ret_value; /* Return value */
+ hbool_t deleted = FALSE; /* Whether the object was deleted */
+ int ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5O_link, FAIL)
@@ -1583,29 +1587,30 @@ H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id)
HDassert(loc->file);
HDassert(H5F_addr_defined(loc->addr));
- /* Get header */
- oh_acc = adjust ? H5AC_WRITE : H5AC_READ;
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, oh_acc)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
+ /* Pin the object header */
+ if(NULL == (oh = H5O_pin(loc, dxpl_id)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
/* Call the "real" link routine */
- if((ret_value = H5O_link_oh(loc->file, adjust, dxpl_id, oh, &oh_flags)) < 0)
+ if((ret_value = H5O_link_oh(loc->file, adjust, dxpl_id, oh, &deleted)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust object link count")
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
+ if(ret_value >= 0 && deleted && H5O_delete(loc->file, dxpl_id, loc->addr) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_link() */
/*-------------------------------------------------------------------------
- * Function: H5O_pin
+ * Function: H5O_protect
*
- * Purpose: Pin an object header down for use during a sequence of message
- * operations, which prevents the object header from being
- * evicted from the cache.
+ * Purpose: Wrapper around H5AC_protect for use during a H5O_protect->
+ * H5O_msg_append->...->H5O_msg_append->H5O_unprotect sequence of calls
+ * during an object's creation.
*
* Return: Success: Pointer to the object header structure for the
* object.
@@ -1618,12 +1623,15 @@ done:
*-------------------------------------------------------------------------
*/
H5O_t *
-H5O_pin(H5O_loc_t *loc, hid_t dxpl_id)
+H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot)
{
- H5O_t *oh = NULL; /* Object header */
- H5O_t *ret_value; /* Return value */
+ H5O_t *oh = NULL; /* Object header protected */
+ H5O_cache_ud_t udata; /* User data for protecting object header */
+ H5O_cont_msgs_t cont_msg_info; /* Continuation message info */
+ unsigned file_intent; /* R/W intent on file */
+ H5O_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5O_pin, NULL)
+ FUNC_ENTER_NOAPI(H5O_protect, NULL)
/* check args */
HDassert(loc);
@@ -1631,29 +1639,228 @@ H5O_pin(H5O_loc_t *loc, hid_t dxpl_id)
HDassert(H5F_addr_defined(loc->addr));
/* Check for write access on the file */
- if(0 == (H5F_INTENT(loc->file) & H5F_ACC_RDWR))
+ file_intent = H5F_INTENT(loc->file);
+ if((prot == H5AC_WRITE) && (0 == (file_intent & H5F_ACC_RDWR)))
HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "no write intent on file")
+ /* Construct the user data for protect callback */
+ udata.made_attempt = FALSE;
+ udata.v1_pfx_nmesgs = 0;
+ udata.common.f = loc->file;
+ udata.common.dxpl_id = dxpl_id;
+ udata.common.file_intent = file_intent;
+ udata.common.merged_null_msgs = 0;
+ udata.common.mesgs_modified = FALSE;
+ HDmemset(&cont_msg_info, 0, sizeof(cont_msg_info));
+ udata.common.cont_msg_info = &cont_msg_info;
+
/* Lock the object header into the cache */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, &udata, prot)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header")
- /* Check if the object header needs to be pinned */
- if(0 == oh->npins) {
- /* Mark object header as un-evictable */
- if(H5AC_pin_protected_entry(oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, NULL, "unable to pin object header")
+ /* Check if there are any continuation messages to process */
+ if(cont_msg_info.nmsgs > 0) {
+ size_t curr_msg; /* Current continuation message to process */
+ H5O_chk_cache_ud_t chk_udata; /* User data for loading chunk */
+
+ /* Sanity check - we should only have continuation messages to process
+ * when the object header is actually loaded from the file.
+ */
+ HDassert(udata.made_attempt == TRUE);
+
+ /* Construct the user data for protecting chunks */
+ chk_udata.decoding = TRUE;
+ chk_udata.oh = oh;
+ chk_udata.chunkno = UINT_MAX; /* Set to invalid value, for better error detection */
+ chk_udata.common.f = loc->file;
+ chk_udata.common.dxpl_id = dxpl_id;
+ chk_udata.common.file_intent = file_intent;
+ chk_udata.common.merged_null_msgs = udata.common.merged_null_msgs;
+ chk_udata.common.mesgs_modified = udata.common.mesgs_modified;
+ chk_udata.common.cont_msg_info = &cont_msg_info;
+
+ /* Read in continuation messages, until there are no more */
+ curr_msg = 0;
+ while(curr_msg < cont_msg_info.nmsgs) {
+ H5O_chunk_proxy_t *chk_proxy; /* Proxy for chunk, to bring it into memory */
+#ifndef NDEBUG
+ unsigned chkcnt = oh->nchunks; /* Count of chunks (for sanity checking) */
+#endif /* NDEBUG */
+
+ /* Bring the chunk into the cache */
+ /* (which adds to the object header */
+ chk_udata.chunk_size = cont_msg_info.msgs[curr_msg].size;
+ if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, NULL, &chk_udata, prot)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header chunk")
+
+ /* Sanity check */
+ HDassert(chk_proxy->oh == oh);
+ HDassert(chk_proxy->chunkno == chkcnt);
+ HDassert(oh->nchunks == (chkcnt + 1));
+
+ /* Release the chunk from the cache */
+ if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, chk_proxy, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header chunk")
+
+ /* Advance to next continuation message */
+ curr_msg++;
+ } /* end while */
+
+ /* Release any continuation messages built up */
+ if(cont_msg_info.msgs)
+ cont_msg_info.msgs = (H5O_cont_t *)H5FL_SEQ_FREE(H5O_cont_t, cont_msg_info.msgs);
+
+ /* Pass back out some of the chunk's user data */
+ udata.common.merged_null_msgs = chk_udata.common.merged_null_msgs;
+ udata.common.mesgs_modified = chk_udata.common.mesgs_modified;
} /* end if */
- /* Increment the pin count */
- oh->npins++;
+ /* Check for incorrect # of object header messages, if we've just loaded
+ * this object header from the file
+ */
+ if(udata.made_attempt) {
+ /* Check for incorrect # of messages in v1 object header */
+ if(oh->version == H5O_VERSION_1 &&
+ (oh->nmesgs + udata.common.merged_null_msgs) != udata.v1_pfx_nmesgs) {
+/* Don't enforce the error on an incorrect # of object header messages bug
+ * unless strict format checking is enabled. This allows for older
+ * files, created with a version of the library that had a bug in tracking
+ * the correct # of header messages to be read in without the library
+ * erroring out here. -QAK
+ */
+#ifdef H5_STRICT_FORMAT_CHECKS
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - incorrect # of messages")
+#else /* H5_STRICT_FORMAT_CHECKS */
+ /* Mark object header prefix dirty later if we don't have write access */
+ /* (object header will have been marked dirty during protect, if we
+ * have write access -QAK)
+ */
+ if(prot != H5AC_WRITE)
+ oh->prefix_modified = TRUE;
+#ifndef NDEBUG
+ else {
+ unsigned oh_status = 0; /* Object header entry cache status */
+
+ /* Check the object header's status in the metadata cache */
+ if(H5AC_get_entry_status(loc->file, loc->addr, &oh_status) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to check metadata cache status for object header")
+
+ /* Make certain that object header is not dirty */
+ HDassert(!(oh_status & H5AC_ES__IS_DIRTY));
+ } /* end else */
+#endif /* NDEBUG */
+#endif /* H5_STRICT_FORMAT_CHECKS */
+ } /* end if */
+
+ /* Check for any messages that were modified while being read in */
+ if(udata.common.mesgs_modified && prot != H5AC_WRITE)
+ oh->mesgs_modified = TRUE;
+ } /* end if */
+
+ /* Take care of loose ends for modifications made while bringing in the
+ * object header & chunks.
+ */
+ if(prot == H5AC_WRITE) {
+ /* Check for the object header prefix being modified somehow */
+ /* (usually through updating the # of object header messages) */
+ if(oh->prefix_modified) {
+ /* Mark the header as dirty now */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, NULL, "unable to mark object header as dirty")
+
+ /* Reset flag */
+ oh->prefix_modified = FALSE;
+ } /* end if */
+
+ /* Check for deferred dirty messages */
+ if(oh->mesgs_modified) {
+ unsigned u; /* Local index variable */
+
+ /* Loop through all messages, marking their chunks as dirty */
+ /* (slightly inefficient, since we don't know exactly which messages
+ * were modified when the object header & chunks were brought in
+ * from the file, but this only can happen once per load -QAK)
+ */
+ for(u = 0; u < oh->nmesgs; u++) {
+ /* Mark each chunk with a dirty message as dirty also */
+ if(oh->mesg[u].dirty) {
+ H5O_chunk_proxy_t *chk_proxy; /* Chunk that message is in */
+
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(loc->file, dxpl_id, oh, oh->mesg[u].chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header chunk")
+
+ /* Unprotect chunk, marking it dirty */
+ if(H5O_chunk_unprotect(loc->file, dxpl_id, oh, chk_proxy, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to unprotect object header chunk")
+ } /* end if */
+ } /* end for */
+
+ /* Reset flag */
+ oh->mesgs_modified = FALSE;
+ } /* end if */
+ } /* end if */
+
+#ifdef H5O_DEBUG
+H5O_assert(oh);
+#endif /* H5O_DEBUG */
+
+ /* Set return value */
+ ret_value = oh;
+
+done:
+ if(ret_value == NULL && oh) {
+ if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_protect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_pin
+ *
+ * Purpose: Pin an object header down for use during a sequence of message
+ * operations, which prevents the object header from being
+ * evicted from the cache.
+ *
+ * Return: Success: Pointer to the object header structure for the
+ * object.
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+H5O_t *
+H5O_pin(const H5O_loc_t *loc, hid_t dxpl_id)
+{
+ H5O_t *oh = NULL; /* Object header */
+ H5O_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_pin, NULL)
+
+ /* check args */
+ HDassert(loc);
+
+ /* Get header */
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header")
+
+ /* Increment the reference count on the object header */
+ /* (which will pin it, if appropriate) */
+ if(H5O_inc_rc(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "unable to increment reference count on object header")
/* Set the return value */
ret_value = oh;
done:
/* Release the object header from the cache */
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, ret_value, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1670,8 +1877,8 @@ done:
* Failure: Negative
*
* Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Dec 31 2002
+ * koziol@hdfgroup.org
+ * Jul 13 2008
*
*-------------------------------------------------------------------------
*/
@@ -1685,15 +1892,10 @@ H5O_unpin(H5O_t *oh)
/* check args */
HDassert(oh);
- /* Check if this is the last unpin operation */
- if(1 == oh->npins) {
- /* Mark object header as evictable again */
- if(H5AC_unpin_entry(oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
- } /* end if */
-
- /* Decrement the pin count */
- oh->npins--;
+ /* Decrement the reference count on the object header */
+ /* (which will unpin it, if appropriate) */
+ if(H5O_dec_rc(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement reference count on object header")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1701,6 +1903,42 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_unprotect
+ *
+ * Purpose: Wrapper around H5AC_unprotect for use during a H5O_protect->
+ * H5O_msg_append->...->H5O_msg_append->H5O_unprotect sequence of calls
+ * during an object's creation.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Dec 31 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_unprotect(const H5O_loc_t *loc, hid_t dxpl_id, H5O_t *oh, unsigned oh_flags)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_unprotect, FAIL)
+
+ /* check args */
+ HDassert(loc);
+ HDassert(oh);
+
+ /* Unprotect the object header */
+ if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, oh->chunk[0].addr, oh, oh_flags) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_unprotect() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_touch_oh
*
* Purpose: If FORCE is non-zero then create a modification time message
@@ -1717,6 +1955,8 @@ done:
herr_t
H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hbool_t force)
{
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */
+ unsigned chk_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting chunk */
time_t now; /* Current time */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1755,6 +1995,10 @@ H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hbool_t force)
oh->mesg[idx].flags = (uint8_t)mesg_flags;
} /* end if */
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, oh->mesg[idx].chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
/* Allocate 'native' space, if necessary */
if(NULL == oh->mesg[idx].native) {
if(NULL == (oh->mesg[idx].native = H5FL_MALLOC(time_t)))
@@ -1766,19 +2010,24 @@ H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hbool_t force)
/* Mark the message as dirty */
oh->mesg[idx].dirty = TRUE;
+ chk_flags |= H5AC__DIRTIED_FLAG;
} /* end if */
else {
/* XXX: For now, update access time & change fields in the object header */
/* (will need to add some code to update modification time appropriately) */
oh->atime = oh->ctime = now;
- } /* end else */
- /* Mark object header as dirty in cache */
- if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
+ /* Mark object header as dirty in cache */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
+ } /* end else */
} /* end if */
done:
+ /* Release chunk */
+ if(chk_proxy && H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy, chk_flags) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_touch_oh() */
@@ -1809,13 +2058,9 @@ H5O_touch(const H5O_loc_t *loc, hbool_t force, hid_t dxpl_id)
/* check args */
HDassert(loc);
- HDassert(loc->file);
- HDassert(H5F_addr_defined(loc->addr));
- if(0 == (H5F_INTENT(loc->file) & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_WRITE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Create/Update the modification time message */
@@ -1826,7 +2071,7 @@ H5O_touch(const H5O_loc_t *loc, hbool_t force, hid_t dxpl_id)
oh_flags |= H5AC__DIRTIED_FLAG;
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, oh_flags) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1915,6 +2160,8 @@ herr_t
H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
{
H5O_t *oh = NULL; /* Object header information */
+ H5O_loc_t loc; /* Object location for object to delete */
+ unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting object header */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5O_delete, FAIL)
@@ -1923,16 +2170,24 @@ H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
HDassert(f);
HDassert(H5F_addr_defined(addr));
+ /* Set up the object location */
+ loc.file = f;
+ loc.addr = addr;
+ loc.holding_file = FALSE;
+
/* Get the object header information */
- if(NULL == (oh = (H5O_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (oh = H5O_protect(&loc, dxpl_id, H5AC_WRITE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Delete object */
if(H5O_delete_oh(f, dxpl_id, oh) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
+ /* Mark object header as deleted */
+ oh_flags = H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
+
done:
- if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ if(oh && H5O_unprotect(&loc, dxpl_id, oh, oh_flags) < 0)
HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -2005,7 +2260,7 @@ H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type, hid_t dxpl_id)
FUNC_ENTER_NOAPI(H5O_obj_type, FAIL)
/* Load the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Retrieve the type of the object */
@@ -2013,7 +2268,7 @@ H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type, hid_t dxpl_id)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ 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")
FUNC_LEAVE_NOAPI(ret_value)
@@ -2083,7 +2338,7 @@ H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id)
FUNC_ENTER_NOAPI_NOINIT(H5O_obj_class)
/* Load the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header")
/* Test whether entry qualifies as a particular type of object */
@@ -2091,7 +2346,7 @@ H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine object type")
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -2354,7 +2609,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_get_hdr_info(const H5O_loc_t *oloc, hid_t dxpl_id, H5O_hdr_info_t *hdr)
+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 */
@@ -2362,14 +2617,14 @@ H5O_get_hdr_info(const H5O_loc_t *oloc, hid_t dxpl_id, H5O_hdr_info_t *hdr)
FUNC_ENTER_NOAPI(H5O_get_hdr_info, FAIL)
/* Check args */
- HDassert(oloc);
+ HDassert(loc);
HDassert(hdr);
/* Reset the object header info structure */
HDmemset(hdr, 0, sizeof(*hdr));
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ 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 */
@@ -2377,7 +2632,7 @@ H5O_get_hdr_info(const H5O_loc_t *oloc, hid_t dxpl_id, H5O_hdr_info_t *hdr)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object header info")
done:
- if(oh && H5AC_unprotect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ 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)
@@ -2493,7 +2748,7 @@ H5O_get_info(const H5O_loc_t *loc, hid_t dxpl_id, hbool_t want_ih_info,
HDassert(oinfo);
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Reset the object info structure */
@@ -2581,7 +2836,7 @@ H5O_get_info(const H5O_loc_t *loc, hid_t dxpl_id, hbool_t want_ih_info,
} /* end if */
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ 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")
FUNC_LEAVE_NOAPI(ret_value)
@@ -2614,7 +2869,7 @@ H5O_get_create_plist(const H5O_loc_t *loc, hid_t dxpl_id, H5P_genplist_t *oc_pli
HDassert(oc_plist);
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Set property values, if they were used for the object */
@@ -2636,7 +2891,7 @@ H5O_get_create_plist(const H5O_loc_t *loc, hid_t dxpl_id, H5P_genplist_t *oc_pli
} /* end if */
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ 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")
FUNC_LEAVE_NOAPI(ret_value)
@@ -2669,14 +2924,14 @@ H5O_get_nlinks(const H5O_loc_t *loc, hid_t dxpl_id, hsize_t *nlinks)
HDassert(nlinks);
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Retrieve the # of link messages seen when the object header was loaded */
*nlinks = oh->link_msgs_seen;
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ 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")
FUNC_LEAVE_NOAPI(ret_value)
@@ -2784,22 +3039,22 @@ H5O_get_rc_and_type(const H5O_loc_t *loc, hid_t dxpl_id, unsigned *rc, H5O_type_
/* Check args */
HDassert(loc);
- HDassert(rc);
- HDassert(otype);
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Set the object's reference count */
- *rc = oh->nlink;
+ if(rc)
+ *rc = oh->nlink;
/* Retrieve the type of the object */
- if(H5O_obj_type_real(oh, otype) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
+ if(otype)
+ if(H5O_obj_type_real(oh, otype) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ 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")
FUNC_LEAVE_NOAPI(ret_value)
@@ -2823,7 +3078,7 @@ H5O_free_visit_visited(void *item, void UNUSED *key, void UNUSED *operator_data/
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_free_visit_visited)
- (void)H5FL_FREE(H5_obj_t, item);
+ item = H5FL_FREE(H5_obj_t, item);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_free_visit_visited() */
@@ -3062,6 +3317,78 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_inc_rc
+ *
+ * Purpose: Increments the reference count on an object header
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_inc_rc(H5O_t *oh)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_inc_rc, FAIL)
+
+ /* check args */
+ HDassert(oh);
+
+ /* Pin the object header when the reference count goes above 0 */
+ if(oh->rc == 0)
+ if(H5AC_pin_protected_entry(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
+
+ /* Increment reference count */
+ oh->rc++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_inc_rc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_dec_rc
+ *
+ * Purpose: Decrements the reference count on an object header
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_dec_rc(H5O_t *oh)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_dec_rc, FAIL)
+
+ /* check args */
+ HDassert(oh);
+
+ /* Decrement reference count */
+ oh->rc--;
+
+ /* Unpin the object header when the reference count goes back to 0 */
+ if(oh->rc == 0)
+ if(H5AC_unpin_entry(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_dec_rc() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_free
*
* Purpose: Destroys an object header.
@@ -3086,12 +3413,8 @@ H5O_free(H5O_t *oh)
/* Destroy chunks */
if(oh->chunk) {
- for(u = 0; u < oh->nchunks; u++) {
- /* Verify that chunk is clean */
- HDassert(oh->chunk[u].dirty == 0);
-
+ for(u = 0; u < oh->nchunks; u++)
oh->chunk[u].image = H5FL_BLK_FREE(chunk_image, oh->chunk[u].image);
- } /* end for */
oh->chunk = (H5O_chunk_t *)H5FL_SEQ_FREE(H5O_chunk_t, oh->chunk);
} /* end if */
diff --git a/src/H5Oalloc.c b/src/H5Oalloc.c
index 31e6de7..66630ca 100644
--- a/src/H5Oalloc.c
+++ b/src/H5Oalloc.c
@@ -58,21 +58,24 @@
/* Local Prototypes */
/********************/
-static herr_t H5O_add_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
- uint8_t *new_gap_loc, size_t new_gap_size);
-static herr_t H5O_eliminate_gap(H5O_t *oh, H5O_mesg_t *mesg,
- uint8_t *new_gap_loc, size_t new_gap_size);
-static herr_t H5O_alloc_null(H5O_t *oh, unsigned null_idx,
+static herr_t H5O_add_gap(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
+ H5O_chunk_proxy_t *chk_proxy, unsigned *chk_flags,
+ unsigned idx, uint8_t *new_gap_loc, size_t new_gap_size);
+static herr_t H5O_eliminate_gap(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
+ H5O_chunk_proxy_t *chk_proxy, unsigned *chk_flags,
+ H5O_mesg_t *mesg, uint8_t *new_gap_loc, size_t new_gap_size);
+static herr_t H5O_alloc_null(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned null_idx,
const H5O_msg_class_t *new_type, void *new_native, size_t new_size);
static htri_t H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
unsigned chunkno, size_t size, unsigned * msg_idx);
static unsigned H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
size_t size);
-static htri_t H5O_move_cont(H5F_t *f, H5O_t *oh, unsigned cont_u, hid_t dxpl_id);
-static htri_t H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id);
-static htri_t H5O_merge_null(H5F_t *f, H5O_t *oh, hid_t dxpl_id);
+static htri_t H5O_move_cont(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned cont_u);
+static htri_t H5O_move_msgs_forward(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
+static htri_t H5O_merge_null(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
static htri_t H5O_remove_empty_chunks(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
-static herr_t H5O_alloc_shrink_chunk(H5F_t *f, H5O_t *oh, hid_t dxpl_id, unsigned chunkno);
+static herr_t H5O_alloc_shrink_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
+ unsigned chunkno);
/*********************/
@@ -108,8 +111,8 @@ H5FL_EXTERN(H5O_cont_t);
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_add_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
- uint8_t *new_gap_loc, size_t new_gap_size)
+H5O_add_gap(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_chunk_proxy_t *chk_proxy,
+ unsigned *chk_flags, unsigned idx, uint8_t *new_gap_loc, size_t new_gap_size)
{
hbool_t merged_with_null; /* Whether the gap was merged with a null message */
unsigned u; /* Local index variable */
@@ -120,6 +123,8 @@ H5O_add_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
/* check args */
HDassert(oh);
HDassert(oh->version > H5O_VERSION_1);
+ HDassert(chk_proxy);
+ HDassert(chk_flags);
HDassert(new_gap_loc);
HDassert(new_gap_size);
@@ -128,13 +133,13 @@ H5O_add_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
for(u = 0; u < oh->nmesgs && !merged_with_null; u++) {
/* Find a null message in the chunk with the new gap */
/* (a null message that's not the one we are eliminating) */
- if(H5O_NULL_ID == oh->mesg[u].type->id && oh->mesg[u].chunkno == chunkno
+ if(H5O_NULL_ID == oh->mesg[u].type->id && oh->mesg[u].chunkno == chk_proxy->chunkno
&& u != idx) {
/* Sanity check - chunks with null messages shouldn't have a gap */
- HDassert(oh->chunk[chunkno].gap == 0);
+ HDassert(oh->chunk[chk_proxy->chunkno].gap == 0);
/* Eliminate the gap in the chunk */
- if(H5O_eliminate_gap(oh, &oh->mesg[u], new_gap_loc, new_gap_size) < 0)
+ if(H5O_eliminate_gap(f, dxpl_id, oh, chk_proxy, chk_flags, &oh->mesg[u], new_gap_loc, new_gap_size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't eliminate gap in chunk")
/* Set flag to indicate that the gap was handled */
@@ -146,15 +151,15 @@ H5O_add_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
if(!merged_with_null) {
/* Adjust message offsets after new gap forward in chunk */
for(u = 0; u < oh->nmesgs; u++)
- if(oh->mesg[u].chunkno == chunkno && oh->mesg[u].raw > new_gap_loc)
+ if(oh->mesg[u].chunkno == chk_proxy->chunkno && oh->mesg[u].raw > new_gap_loc)
oh->mesg[u].raw -= new_gap_size;
/* Slide raw message info forward in chunk image */
HDmemmove(new_gap_loc, new_gap_loc + new_gap_size,
- (size_t)((oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh))) - (new_gap_loc + new_gap_size)));
+ (size_t)((oh->chunk[chk_proxy->chunkno].image + (oh->chunk[chk_proxy->chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh))) - (new_gap_loc + new_gap_size)));
/* Add existing gap size to new gap size */
- new_gap_size += oh->chunk[chunkno].gap;
+ new_gap_size += oh->chunk[chk_proxy->chunkno].gap;
/* Merging with existing gap will allow for a new null message */
if(new_gap_size >= (size_t)H5O_SIZEOF_MSGHDR_OH(oh)) {
@@ -166,16 +171,16 @@ H5O_add_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate more space for messages")
/* Increment new gap size */
- oh->chunk[chunkno].gap += new_gap_size;
+ oh->chunk[chk_proxy->chunkno].gap += new_gap_size;
/* Create new null message, with the tail of the previous null message */
null_msg = &(oh->mesg[oh->nmesgs++]);
null_msg->type = H5O_MSG_NULL;
null_msg->native = NULL;
null_msg->raw_size = new_gap_size - H5O_SIZEOF_MSGHDR_OH(oh);
- null_msg->raw = (oh->chunk[chunkno].image + oh->chunk[chunkno].size)
+ null_msg->raw = (oh->chunk[chk_proxy->chunkno].image + oh->chunk[chk_proxy->chunkno].size)
- (H5O_SIZEOF_CHKSUM_OH(oh) + null_msg->raw_size);
- null_msg->chunkno = chunkno;
+ null_msg->chunkno = chk_proxy->chunkno;
/* Zero out new null message's raw data */
if(null_msg->raw_size)
@@ -185,10 +190,13 @@ H5O_add_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
null_msg->dirty = TRUE;
/* Reset size of gap in chunk */
- oh->chunk[chunkno].gap = 0;
+ oh->chunk[chk_proxy->chunkno].gap = 0;
} /* end if */
else
- oh->chunk[chunkno].gap = new_gap_size;
+ oh->chunk[chk_proxy->chunkno].gap = new_gap_size;
+
+ /* Mark the chunk as modified */
+ *chk_flags |= H5AC__DIRTIED_FLAG;
} /* end if */
done:
@@ -199,7 +207,14 @@ done:
/*-------------------------------------------------------------------------
* Function: H5O_eliminate_gap
*
- * Purpose: Eliminate a gap in a chunk with a null message
+ * Purpose: Eliminate a gap in a chunk with a null message.
+ *
+ * Note: Sometimes this happens as a result of converting an existing
+ * non-null message to a null message, so we zero out the gap
+ * here, even though it might already be zero (when we're adding
+ * a gap to a chunk with an existing null message). (Mostly,
+ * this just simplifies the code, esp. with the necessary chunk
+ * locking -QAK)
*
* Return: Non-negative on success/Negative on failure
*
@@ -210,16 +225,20 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_eliminate_gap(H5O_t *oh, H5O_mesg_t *mesg, uint8_t *gap_loc, size_t gap_size)
+H5O_eliminate_gap(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_chunk_proxy_t *chk_proxy,
+ unsigned *chk_flags, H5O_mesg_t *mesg, uint8_t *gap_loc, size_t gap_size)
{
uint8_t *move_start, *move_end; /* Pointers to area of messages to move */
hbool_t null_before_gap; /* Flag whether the null message is before the gap or not */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_eliminate_gap)
+ FUNC_ENTER_NOAPI_NOINIT(H5O_eliminate_gap)
/* check args */
HDassert(oh);
HDassert(oh->version > H5O_VERSION_1);
+ HDassert(chk_proxy);
+ HDassert(chk_flags);
HDassert(mesg);
HDassert(gap_loc);
HDassert(gap_size);
@@ -242,6 +261,7 @@ H5O_eliminate_gap(H5O_t *oh, H5O_mesg_t *mesg, uint8_t *gap_loc, size_t gap_size
unsigned u; /* Local index variable */
/* Look for messages that need to move, to adjust raw pointers in chunk */
+ /* (this doesn't change the moved messages 'dirty' state) */
for(u = 0; u < oh->nmesgs; u++) {
uint8_t *msg_start; /* Start of encoded message in chunk */
@@ -282,10 +302,15 @@ H5O_eliminate_gap(H5O_t *oh, H5O_mesg_t *mesg, uint8_t *gap_loc, size_t gap_size
/* Adjust size of null message */
mesg->raw_size += gap_size;
+ /* Set the gap size to zero for the chunk */
+ oh->chunk[mesg->chunkno].gap = 0;
+
/* Mark null message as dirty */
mesg->dirty = TRUE;
+ *chk_flags |= H5AC__DIRTIED_FLAG;
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_eliminate_gap() */
@@ -304,9 +329,11 @@ H5O_eliminate_gap(H5O_t *oh, H5O_mesg_t *mesg, uint8_t *gap_loc, size_t gap_size
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_alloc_null(H5O_t *oh, unsigned null_idx, const H5O_msg_class_t *new_type,
- void *new_native, size_t new_size)
+H5O_alloc_null(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned null_idx,
+ const H5O_msg_class_t *new_type, void *new_native, size_t new_size)
{
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */
+ unsigned chk_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting chunk */
H5O_mesg_t *alloc_msg; /* Pointer to null message to allocate out of */
herr_t ret_value = SUCCEED; /* Return value */
@@ -320,6 +347,10 @@ H5O_alloc_null(H5O_t *oh, unsigned null_idx, const H5O_msg_class_t *new_type,
/* Point to null message to allocate out of */
alloc_msg = &oh->mesg[null_idx];
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, alloc_msg->chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
/* Check if there's a need to split the null message */
if(alloc_msg->raw_size > new_size) {
/* Check for producing a gap in the chunk */
@@ -330,7 +361,7 @@ H5O_alloc_null(H5O_t *oh, unsigned null_idx, const H5O_msg_class_t *new_type,
alloc_msg->raw_size = new_size;
/* Add the gap to the chunk */
- if(H5O_add_gap(oh, alloc_msg->chunkno, null_idx, alloc_msg->raw + alloc_msg->raw_size, gap_size) < 0)
+ if(H5O_add_gap(f, dxpl_id, oh, chk_proxy, &chk_flags, null_idx, alloc_msg->raw + alloc_msg->raw_size, gap_size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert gap in chunk")
} /* end if */
else {
@@ -356,19 +387,17 @@ H5O_alloc_null(H5O_t *oh, unsigned null_idx, const H5O_msg_class_t *new_type,
/* Mark the message as dirty */
null_msg->dirty = TRUE;
+ chk_flags |= H5AC__DIRTIED_FLAG;
/* Check for gap in new null message's chunk */
if(oh->chunk[null_msg->chunkno].gap > 0) {
unsigned null_chunkno = null_msg->chunkno; /* Chunk w/gap */
/* Eliminate the gap in the chunk */
- if(H5O_eliminate_gap(oh, null_msg,
+ if(H5O_eliminate_gap(f, dxpl_id, oh, chk_proxy, &chk_flags, null_msg,
((oh->chunk[null_chunkno].image + oh->chunk[null_chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[null_chunkno].gap)),
oh->chunk[null_chunkno].gap) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTREMOVE, FAIL, "can't eliminate gap in chunk")
-
- /* Set the gap size to zero for the chunk */
- oh->chunk[null_chunkno].gap = 0;
} /* end if */
/* Set the size of the new "real" message */
@@ -382,8 +411,13 @@ H5O_alloc_null(H5O_t *oh, unsigned null_idx, const H5O_msg_class_t *new_type,
/* Mark the new message as dirty */
alloc_msg->dirty = TRUE;
+ chk_flags |= H5AC__DIRTIED_FLAG;
done:
+ /* Release chunk */
+ if(chk_proxy && H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy, chk_flags) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_alloc_null() */
@@ -467,6 +501,8 @@ static htri_t
H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned chunkno,
size_t size, unsigned * msg_idx)
{
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */
+ unsigned chk_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting chunk */
size_t delta; /* Change in chunk's size */
size_t aligned_size = H5O_ALIGN_OH(oh, size);
uint8_t *old_image; /* Old address of chunk's image in memory */
@@ -500,7 +536,7 @@ H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned chunkno,
== ((oh->chunk[chunkno].image + oh->chunk[chunkno].size) -
(oh->chunk[chunkno].gap + H5O_SIZEOF_CHKSUM_OH(oh))))) {
- extend_msg = u;
+ extend_msg = (int)u;
break;
} /* end if */
} /* end for */
@@ -516,7 +552,10 @@ H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned chunkno,
/* Check for changing the chunk #0 data size enough to need adjusting the flags */
if(oh->version > H5O_VERSION_1 && chunkno == 0) {
- uint64_t chunk0_size = oh->chunk[0].size - H5O_SIZEOF_HDR(oh); /* Size of chunk 0's data */
+ uint64_t chunk0_size; /* Size of chunk 0's data */
+
+ HDassert(oh->chunk[0].size >= (size_t)H5O_SIZEOF_HDR(oh));
+ chunk0_size = oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh);
/* Check for moving from a 1-byte to a 2-byte size encoding */
if(chunk0_size <= 255 && (chunk0_size + delta) > 255) {
@@ -546,16 +585,23 @@ H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned chunkno,
else if(extended == FALSE) /* can't extend -- we are done */
HGOTO_DONE(FALSE)
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
/* Adjust object header prefix flags */
if(adjust_size_flags) {
- oh->flags &= ~H5O_HDR_CHUNK0_SIZE;
+ oh->flags &= (uint8_t)~H5O_HDR_CHUNK0_SIZE;
oh->flags |= new_size_flags;
+
+ /* Mark object header as dirty in cache */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
} /* end if */
/* If we can extend an existing null message, take care of that */
if(extend_msg >= 0) {
/* Adjust message size of existing null message */
- oh->mesg[extend_msg].dirty = TRUE;
oh->mesg[extend_msg].raw_size += delta;
} /* end if */
/* Create new null message for end of chunk */
@@ -566,11 +612,10 @@ H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned chunkno,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate more space for messages")
/* Set extension message */
- extend_msg = oh->nmesgs++;
+ extend_msg = (int)oh->nmesgs++;
/* Initialize new null message */
oh->mesg[extend_msg].type = H5O_MSG_NULL;
- oh->mesg[extend_msg].dirty = TRUE;
oh->mesg[extend_msg].native = NULL;
oh->mesg[extend_msg].raw = ((oh->chunk[chunkno].image + oh->chunk[chunkno].size)
- (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[chunkno].gap))
@@ -579,13 +624,16 @@ H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned chunkno,
oh->mesg[extend_msg].chunkno = chunkno;
} /* end else */
+ /* Mark the extended message as dirty */
+ oh->mesg[extend_msg].dirty = TRUE;
+ chk_flags |= H5AC__DIRTIED_FLAG;
+
/* Allocate more memory space for chunk's image */
old_image = oh->chunk[chunkno].image;
old_size = oh->chunk[chunkno].size;
oh->chunk[chunkno].size += delta + extra_prfx_size;
oh->chunk[chunkno].image = H5FL_BLK_REALLOC(chunk_image, old_image, oh->chunk[chunkno].size);
oh->chunk[chunkno].gap = 0;
- oh->chunk[chunkno].dirty = TRUE;
if(NULL == oh->chunk[chunkno].image)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
@@ -599,6 +647,7 @@ H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned chunkno,
oh->mesg[u].raw = oh->chunk[chunkno].image + extra_prfx_size + (oh->mesg[u].raw - old_image);
/* Flag message as dirty directly */
+ /* (we mark the entire chunk dirty when we update its size) */
oh->mesg[u].dirty = TRUE;
} /* endif */
@@ -607,19 +656,39 @@ H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned chunkno,
* it's size is directly encoded in the object header) */
if(chunkno > 0 && (H5O_CONT_ID == oh->mesg[u].type->id) &&
(((H5O_cont_t *)(oh->mesg[u].native))->chunkno == chunkno)) {
+ H5O_chunk_proxy_t *chk_proxy2 = NULL; /* Chunk that continuation message is in */
+ unsigned chk_flags2 = H5AC__NO_FLAGS_SET; /* Flags for unprotecting chunk */
+ unsigned cont_chunkno = oh->mesg[u].chunkno; /* Chunk # for continuation message */
+
+ /* Protect chunk containing continuation message */
+ if(NULL == (chk_proxy2 = H5O_chunk_protect(f, dxpl_id, oh, cont_chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
/* Adjust size in continuation message */
HDassert(((H5O_cont_t *)(oh->mesg[u].native))->size == old_size);
((H5O_cont_t *)(oh->mesg[u].native))->size = oh->chunk[chunkno].size;
/* Flag continuation message as dirty */
oh->mesg[u].dirty = TRUE;
+ chk_flags2 |= H5AC__DIRTIED_FLAG;
+
+ /* Release chunk containing continuation message */
+ if(H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy2, chk_flags2) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
} /* end if */
} /* end for */
+ /* Mark the chunk size in the cache as changed */
+ chk_flags |= H5AC__SIZE_CHANGED_FLAG;
+
/* Set return value */
- *msg_idx = extend_msg;
+ *msg_idx = (unsigned)extend_msg;
done:
+ /* Release chunk */
+ if(chk_proxy && H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy, chk_flags) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_alloc_extend_chunk() */
@@ -672,6 +741,7 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
} alloc_info;
H5O_mesg_t *curr_msg; /* Pointer to current message to operate on */
+ H5O_chunk_proxy_t *chk_proxy; /* Chunk that message is in */
size_t cont_size; /*continuation message size */
size_t multi_size = 0; /* Size of all the messages in the last chunk */
int found_null = (-1); /* Best fit null message */
@@ -707,12 +777,12 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
if(curr_msg->type->id == H5O_NULL_ID) {
if(cont_size == curr_msg->raw_size) {
- found_null = u;
+ found_null = (int)u;
break;
} /* end if */
else if(curr_msg->raw_size > cont_size &&
(found_null < 0 || curr_msg->raw_size < oh->mesg[found_null].raw_size))
- found_null = u;
+ found_null = (int)u;
} /* end if */
else if(curr_msg->type->id == H5O_CONT_ID) {
/* Don't consider continuation messages (for now) */
@@ -753,7 +823,7 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
if(total_size >= cont_size) {
if(curr_msg->type->id == H5O_ATTR_ID) {
if(found_attr.msgno < 0 || total_size < found_attr.total_size) {
- found_attr.msgno = u;
+ found_attr.msgno = (int)u;
found_attr.gap_size = gap_size;
found_attr.null_size = null_size;
found_attr.total_size = total_size;
@@ -762,7 +832,7 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
} /* end if */
else {
if(found_other.msgno < 0 || total_size < found_other.total_size) {
- found_other.msgno = u;
+ found_other.msgno = (int)u;
found_other.gap_size = gap_size;
found_other.null_size = null_size;
found_other.total_size = total_size;
@@ -835,7 +905,6 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
} /* end if */
chunkno = oh->nchunks++;
- oh->chunk[chunkno].dirty = TRUE;
oh->chunk[chunkno].addr = new_chunk_addr;
oh->chunk[chunkno].size = size;
oh->chunk[chunkno].gap = 0;
@@ -861,9 +930,14 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
if(multi_size > 0) {
/* Move all non-null messages in the last chunk to the new chunk. This
* should be extremely rare so we don't care too much about minimizing
- * the space used */
+ * the space used.
+ */
H5O_mesg_t *null_msg; /* Pointer to new null message */
+ /* Protect last chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, chunkno - 1)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, UFAIL, "unable to load object header chunk")
+
/* Copy each message to the new location */
for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++)
if(curr_msg->chunkno == chunkno - 1) {
@@ -888,15 +962,15 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
} /* end if */
/* Create a null message spanning the entire last chunk */
- found_null = oh->nmesgs++;
+ found_null = (int)oh->nmesgs++;
null_msg = &(oh->mesg[found_null]);
null_msg->type = H5O_MSG_NULL;
null_msg->dirty = TRUE;
null_msg->native = NULL;
- null_msg->raw = oh->chunk[chunkno-1].image
+ null_msg->raw = oh->chunk[chunkno - 1].image
+ ((chunkno == 1) ? H5O_SIZEOF_HDR(oh) : H5O_SIZEOF_CHKHDR_OH(oh))
- H5O_SIZEOF_CHKSUM_OH(oh) + H5O_SIZEOF_MSGHDR_OH(oh);
- null_msg->raw_size = oh->chunk[chunkno-1].size
+ null_msg->raw_size = oh->chunk[chunkno - 1].size
- ((chunkno == 1) ? H5O_SIZEOF_HDR(oh) : H5O_SIZEOF_CHKHDR_OH(oh))
- H5O_SIZEOF_MSGHDR_OH(oh);
null_msg->chunkno = chunkno - 1;
@@ -904,16 +978,23 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
HDassert(null_msg->raw_size >= cont_size);
/* Remove any gap in the chunk */
- oh->chunk[chunkno-1].gap = 0;
+ oh->chunk[chunkno - 1].gap = 0;
+ /* Release chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, UFAIL, "unable to unprotect object header chunk")
} else if(found_null < 0) {
/* Move message (that will be replaced with continuation message)
- * to new chunk, if necessary.
- */
+ * to new chunk, if necessary.
+ */
H5O_mesg_t *null_msg; /* Pointer to new null message */
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, oh->mesg[found_other.msgno].chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, UFAIL, "unable to load object header chunk")
+
/* Create null message for space that message to copy currently occupies */
- found_null = oh->nmesgs++;
+ found_null = (int)oh->nmesgs++;
null_msg = &(oh->mesg[found_null]);
null_msg->type = H5O_MSG_NULL;
null_msg->native = NULL;
@@ -922,7 +1003,6 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
null_msg->chunkno = oh->mesg[found_other.msgno].chunkno;
/* Copy the message to move (& its prefix) to its new location */
- /* (Chunk is already dirty, no need to mark it) */
HDmemcpy(p, oh->mesg[found_other.msgno].raw - H5O_SIZEOF_MSGHDR_OH(oh),
oh->mesg[found_other.msgno].raw_size + H5O_SIZEOF_MSGHDR_OH(oh));
@@ -965,6 +1045,10 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
/* Mark the new null message as dirty */
null_msg->dirty = TRUE;
+
+ /* Release chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, UFAIL, "unable to unprotect object header chunk")
} /* end if */
HDassert(found_null >= 0);
@@ -975,9 +1059,13 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
oh->mesg[idx].dirty = TRUE;
oh->mesg[idx].native = NULL;
oh->mesg[idx].raw = p + H5O_SIZEOF_MSGHDR_OH(oh);
- oh->mesg[idx].raw_size = size - (H5O_SIZEOF_CHKHDR_OH(oh) + H5O_SIZEOF_MSGHDR_OH(oh));
+ oh->mesg[idx].raw_size = size - (size_t)(H5O_SIZEOF_CHKHDR_OH(oh) + H5O_SIZEOF_MSGHDR_OH(oh));
oh->mesg[idx].chunkno = chunkno;
+ /* Insert the new chunk into the cache */
+ if(H5O_chunk_add(f, dxpl_id, oh, chunkno) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, UFAIL, "can't add new chunk to cache")
+
/* Initialize the continuation information */
if(NULL == (cont = H5FL_MALLOC(H5O_cont_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed")
@@ -986,7 +1074,7 @@ H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, size_t size)
cont->chunkno = chunkno;
/* Split the null message and point at continuation message */
- if(H5O_alloc_null(oh, (unsigned)found_null, H5O_MSG_CONT, cont, cont_size) < 0)
+ if(H5O_alloc_null(f, dxpl_id, oh, (unsigned)found_null, H5O_MSG_CONT, cont, cont_size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, UFAIL, "can't split null message")
/* Set return value */
@@ -1071,7 +1159,7 @@ H5O_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
} /* end if */
/* Split the null message and point at continuation message */
- if(H5O_alloc_null(oh, idx, type, NULL, aligned_size) < 0)
+ if(H5O_alloc_null(f, dxpl_id, oh, idx, type, NULL, aligned_size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, UFAIL, "can't split null message")
/* Mark object header as dirty in cache */
@@ -1104,6 +1192,8 @@ herr_t
H5O_release_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_mesg_t *mesg,
hbool_t adj_link)
{
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */
+ unsigned chk_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting chunk */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5O_release_mesg, FAIL)
@@ -1120,6 +1210,10 @@ H5O_release_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_mesg_t *mesg,
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
} /* end if */
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, mesg->chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header chunk")
+
/* Free any native information */
H5O_msg_free_mesg(mesg);
@@ -1133,20 +1227,22 @@ H5O_release_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_mesg_t *mesg,
/* Mark the message as modified */
mesg->dirty = TRUE;
+ chk_flags |= H5AC__DIRTIED_FLAG;
/* Check if chunk has a gap currently */
if(oh->chunk[mesg->chunkno].gap) {
/* Eliminate the gap in the chunk */
- if(H5O_eliminate_gap(oh, mesg,
+ if(H5O_eliminate_gap(f, dxpl_id, oh, chk_proxy, &chk_flags, mesg,
((oh->chunk[mesg->chunkno].image + oh->chunk[mesg->chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[mesg->chunkno].gap)),
oh->chunk[mesg->chunkno].gap) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTREMOVE, FAIL, "can't eliminate gap in chunk")
-
- /* Set the gap size to zero for the chunk */
- oh->chunk[mesg->chunkno].gap = 0;
} /* end if */
done:
+ /* Release chunk, if not already done */
+ if(chk_proxy && H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy, chk_flags) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_release_mesg() */
@@ -1165,18 +1261,13 @@ done:
*-------------------------------------------------------------------------
*/
static htri_t
-H5O_move_cont(H5F_t *f, H5O_t *oh, unsigned cont_u, hid_t dxpl_id)
+H5O_move_cont(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned cont_u)
{
- unsigned v; /* local index variable */
- H5O_mesg_t *cont_msg; /* pointer to the continuation message */
- H5O_mesg_t *nonnull_msg; /* pointer to the current message to operate on */
- H5O_mesg_t *null_msg; /* pointer to the current message to operate on */
- size_t total_size=0; /* total size of nonnull messages in the chunk pointed to by cont message */
- size_t move_size=0; /* size of the message to be moved */
- uint8_t *move_start, *move_end; /* pointers to area of messages to move */
- size_t gap_size; /* size of gap produced */
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that continuation message is in */
+ H5O_mesg_t *cont_msg; /* Pointer to the continuation message */
unsigned deleted_chunkno; /* Chunk # to delete */
- htri_t ret_value = FALSE; /* Return value */
+ unsigned chk_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting chunk */
+ htri_t ret_value = TRUE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_move_cont)
@@ -1184,81 +1275,133 @@ H5O_move_cont(H5F_t *f, H5O_t *oh, unsigned cont_u, hid_t dxpl_id)
HDassert(f);
HDassert(oh);
+ /* Get initial information */
cont_msg = &oh->mesg[cont_u];
H5O_LOAD_NATIVE(f, dxpl_id, 0, oh, cont_msg, FAIL)
deleted_chunkno = ((H5O_cont_t *)(cont_msg->native))->chunkno;
- /* proceed further only if continuation message is pointing to the last chunk */
- if(deleted_chunkno != (oh->nchunks - 1))
- HGOTO_DONE(FALSE)
-
- /* find size of all nonnull messages in the chunk pointed to by the continuation message */
- for(v = 0, nonnull_msg = &oh->mesg[0]; v < oh->nmesgs; v++, nonnull_msg++)
- if(nonnull_msg->chunkno == deleted_chunkno && nonnull_msg->type->id != H5O_NULL_ID) {
- HDassert(nonnull_msg->type->id != H5O_CONT_ID);
- total_size += nonnull_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh);
- }
-
- /* check if messages can fit into the continuation message */
- if(total_size && total_size <= (cont_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh))) {
-
- /* convert continuation message into a null message */
- if(H5O_release_mesg(f, dxpl_id, oh, cont_msg, TRUE) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to convert into null message")
-
- move_start = cont_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh);
- move_end = cont_msg->raw + cont_msg->raw_size;
-
- /* move message(s) forward into continuation message */
- for(v = 0, nonnull_msg = &oh->mesg[0]; v < oh->nmesgs; v++, nonnull_msg++)
- if(nonnull_msg->chunkno == deleted_chunkno && nonnull_msg->type->id != H5O_NULL_ID) {
- move_size = nonnull_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh);
- HDmemcpy(move_start, nonnull_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), move_size);
- nonnull_msg->raw = move_start + H5O_SIZEOF_MSGHDR_OH(oh);
- nonnull_msg->chunkno = cont_msg->chunkno;
- nonnull_msg->dirty = TRUE;
- move_start += move_size;
- }
-
- HDassert(move_start <= move_end);
-
- /* check if there is space remaining in the continuation message */
- /* the remaining space can be gap or a null message */
- gap_size = move_end - move_start;
- if(gap_size >= (size_t)H5O_SIZEOF_MSGHDR_OH(oh)) {
- cont_msg->raw_size = gap_size - H5O_SIZEOF_MSGHDR_OH(oh);
- cont_msg->raw = move_start + H5O_SIZEOF_MSGHDR_OH(oh);
- cont_msg->dirty = TRUE;
- } else {
- if(gap_size && (H5O_add_gap(oh, cont_msg->chunkno, cont_u, move_start, gap_size) < 0))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert gap in chunk")
- /* Release any information/memory for continuation message */
- H5O_msg_free_mesg(cont_msg);
- if(cont_u < (oh->nmesgs - 1))
- HDmemmove(&oh->mesg[cont_u], &oh->mesg[cont_u + 1], ((oh->nmesgs - 1) - cont_u) * sizeof(H5O_mesg_t));
- oh->nmesgs--;
- }
-
- /* remove all null messages in deleted chunk from list of messages */
- /* Note: unsigned v wrapping around at the end */
- for (v = oh->nmesgs - 1, null_msg = &oh->mesg[v]; v < oh->nmesgs; v--, null_msg--)
- if(null_msg->type->id == H5O_NULL_ID && null_msg->chunkno == deleted_chunkno) {
+ /* Check if continuation message is pointing to the last chunk */
+ if(deleted_chunkno == (oh->nchunks - 1)) {
+ size_t nonnull_size; /* Total size of nonnull messages in the chunk pointed to by cont message */
+ H5O_mesg_t *curr_msg; /* Pointer to the current message to operate on */
+ size_t gap_size; /* Size of gap produced */
+ unsigned v; /* Local index variable */
+
+ /* Find size of all nonnull messages in the chunk pointed to by the continuation message */
+ nonnull_size = 0;
+ for(v = 0, curr_msg = &oh->mesg[0]; v < oh->nmesgs; v++, curr_msg++)
+ if(curr_msg->chunkno == deleted_chunkno && curr_msg->type->id != H5O_NULL_ID) {
+ HDassert(curr_msg->type->id != H5O_CONT_ID);
+ nonnull_size += curr_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh);
+ } /* end if */
- /* Release any information/memory for message */
- H5O_msg_free_mesg(null_msg);
+ /* Size of gap in chunk w/continuation message */
+ gap_size = oh->chunk[cont_msg->chunkno].gap;
+
+ /* Check if messages can fit into the continuation message + gap size */
+ /* (Could count any null messages in the chunk w/the continuation
+ * message also, but that is pretty complex. -QAK)
+ */
+ if(nonnull_size && nonnull_size <= (gap_size + cont_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh))) {
+ uint8_t *move_start, *move_end; /* Pointers to area of messages to move */
+ unsigned cont_chunkno; /* Chunk number for continuation message */
+
+ /* Get continuation info */
+ move_start = cont_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh);
+ move_end = cont_msg->raw + cont_msg->raw_size;
+ cont_chunkno = cont_msg->chunkno;
+
+ /* Convert continuation message into a null message */
+ if(H5O_release_mesg(f, dxpl_id, oh, cont_msg, TRUE) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to convert into null message")
+
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, cont_chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header chunk")
+
+ /* Move message(s) forward into continuation message */
+ for(v = 0, curr_msg = &oh->mesg[0]; v < oh->nmesgs; v++, curr_msg++)
+ /* Look for messages in chunk to delete */
+ if(curr_msg->chunkno == deleted_chunkno) {
+ /* Move messages out of chunk to delete */
+ if(curr_msg->type->id != H5O_NULL_ID) {
+ size_t move_size; /* Size of the message to be moved */
+
+ /* Compute size of message to move */
+ move_size = curr_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh);
+
+ /* Move message out of deleted chunk */
+ HDmemcpy(move_start, curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), move_size);
+ curr_msg->raw = move_start + H5O_SIZEOF_MSGHDR_OH(oh);
+ curr_msg->chunkno = cont_chunkno;
+ curr_msg->dirty = TRUE;
+ chk_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Adjust location to move messages to */
+ move_start += move_size;
+ } /* end else */
+ } /* end if */
+
+ HDassert(move_start <= (move_end + gap_size));
+
+ /* Check if there is space remaining in the continuation message */
+ /* (The remaining space can be gap or a null message) */
+ gap_size += (size_t)(move_end - move_start);
+ if(gap_size >= (size_t)H5O_SIZEOF_MSGHDR_OH(oh)) {
+ /* Adjust size of null (was continuation) message */
+ cont_msg->raw_size = gap_size - H5O_SIZEOF_MSGHDR_OH(oh);
+ cont_msg->raw = move_start + H5O_SIZEOF_MSGHDR_OH(oh);
+ cont_msg->dirty = TRUE;
+ chk_flags |= H5AC__DIRTIED_FLAG;
+ } /* end if */
+ else {
+ /* Check if there is space that should be a gap */
+ if(gap_size > 0) {
+ /* Convert remnant into gap in chunk */
+ if(H5O_add_gap(f, dxpl_id, oh, chk_proxy, &chk_flags, cont_u, move_start, gap_size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert gap in chunk")
+ } /* end if */
- if(v < (oh->nmesgs - 1))
- HDmemmove(&oh->mesg[v], &oh->mesg[v + 1], ((oh->nmesgs - 1) - v) * sizeof(H5O_mesg_t));
- oh->nmesgs--;
- } /* end if */
+ /* Release any information/memory for continuation message */
+ H5O_msg_free_mesg(cont_msg);
+ if(cont_u < (oh->nmesgs - 1))
+ HDmemmove(&oh->mesg[cont_u], &oh->mesg[cont_u + 1], ((oh->nmesgs - 1) - cont_u) * sizeof(H5O_mesg_t));
+ oh->nmesgs--;
+ } /* end else */
- (void)H5FL_BLK_FREE(chunk_image, oh->chunk[deleted_chunkno].image);
+ /* Move message(s) forward into continuation message */
+ /* Note: unsigned v wrapping around at the end */
+ for(v = oh->nmesgs - 1, curr_msg = &oh->mesg[v]; v < oh->nmesgs; v--, curr_msg--)
+ /* Look for messages in chunk to delete */
+ if(curr_msg->chunkno == deleted_chunkno) {
+ /* Remove all null messages in deleted chunk from list of messages */
+ if(curr_msg->type->id == H5O_NULL_ID) {
+ /* Release any information/memory for message */
+ H5O_msg_free_mesg(curr_msg);
+ chk_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Remove from message list */
+ if(v < (oh->nmesgs - 1))
+ HDmemmove(&oh->mesg[v], &oh->mesg[v + 1], ((oh->nmesgs - 1) - v) * sizeof(H5O_mesg_t));
+ oh->nmesgs--;
+ } /* end if */
+ } /* end if */
- oh->nchunks--;
- ret_value = TRUE;
+ /* Remove chunk from list of chunks */
+ oh->chunk[deleted_chunkno].image = H5FL_BLK_FREE(chunk_image, oh->chunk[deleted_chunkno].image);
+ oh->nchunks--;
+ } /* end if */
+ else
+ ret_value = FALSE;
} /* end if */
+ else
+ ret_value = FALSE;
done:
+ /* Release chunk, if not already done */
+ if(chk_proxy && H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy, chk_flags) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_move_cont() */
@@ -1274,14 +1417,11 @@ done:
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Oct 17 2005
- * Modifications:
- * Feb. 2009: Vailin Choi
- * Add changes to move messages forward into "continuation" message
*
*-------------------------------------------------------------------------
*/
static htri_t
-H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
+H5O_move_msgs_forward(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
{
hbool_t packed_msg; /* Flag to indicate that messages were packed */
hbool_t did_packing = FALSE; /* Whether any messages were packed */
@@ -1323,6 +1463,12 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Don't swap messages if the second message is also a null message */
/* (We'll merge them together later, in another routine) */
if(H5O_NULL_ID != nonnull_msg->type->id) {
+ H5O_chunk_proxy_t *null_chk_proxy; /* Chunk that message is in */
+
+ /* Protect chunk */
+ if(NULL == (null_chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, curr_msg->chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
/* Copy raw data for non-null message to new location */
HDmemmove(curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh),
nonnull_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), nonnull_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh));
@@ -1336,11 +1482,12 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Mark null message dirty */
/* (since we need to re-encode its message header) */
- /* (also, marking this message dirty means we
- * don't have to mark chunk as dirty)
- */
curr_msg->dirty = TRUE;
+ /* Release chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, oh, null_chk_proxy, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+
/* Set the flag to indicate that the null message
* was packed - if its not at the end its chunk,
* we'll move it again on the next pass.
@@ -1357,23 +1504,29 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
} /* end if */
} /* end if */
else {
- H5O_mesg_t *null_msg; /* Pointer to current message to operate on */
- unsigned v; /* Local index variable */
- htri_t status;
+ H5O_mesg_t *null_msg; /* Pointer to current message to operate on */
+ unsigned v; /* Local index variable */
+ /* Check if messages in chunk pointed to can replace continuation message */
if(H5O_CONT_ID == curr_msg->type->id) {
- if((status = H5O_move_cont(f, oh, u, dxpl_id)) < 0)
+ htri_t status; /* Status from moving messages */
+
+ if((status = H5O_move_cont(f, dxpl_id, oh, u)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "Error in moving messages into cont message")
- else if(status > 0) { /* message(s) got moved into "continuation" message */
+ else if(status > 0) { /* Message(s) got moved into "continuation" message */
packed_msg = TRUE;
break;
- }
- }
+ } /* end else-if */
+ } /* end if */
/* Loop over messages again, looking for large enough null message in earlier chunk */
for(v = 0, null_msg = &oh->mesg[0]; v < oh->nmesgs; v++, null_msg++) {
if(H5O_NULL_ID == null_msg->type->id && curr_msg->chunkno > null_msg->chunkno
&& curr_msg->raw_size <= null_msg->raw_size) {
+ H5O_chunk_proxy_t *null_chk_proxy; /* Chunk that null message is in */
+ H5O_chunk_proxy_t *curr_chk_proxy; /* Chunk that message is in */
+ unsigned null_chk_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting null chunk */
+ unsigned curr_chk_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting curr chunk */
unsigned old_chunkno; /* Old message information */
uint8_t *old_raw;
@@ -1381,15 +1534,19 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
old_chunkno = curr_msg->chunkno;
old_raw = curr_msg->raw;
+ /* Protect chunks */
+ if(NULL == (null_chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, null_msg->chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+ if(NULL == (curr_chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, curr_msg->chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
/* Copy raw data for non-null message to new chunk */
HDmemcpy(null_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh), curr_msg->raw_size + H5O_SIZEOF_MSGHDR_OH(oh));
- /* Mark null message's chunk as dirty, since the raw data image changed */
- oh->chunk[null_msg->chunkno].dirty = TRUE;
-
/* Point non-null message at null message's space */
curr_msg->chunkno = null_msg->chunkno;
curr_msg->raw = null_msg->raw;
+ curr_chk_flags |= H5AC__DIRTIED_FLAG;
/* Change information for null message */
if(curr_msg->raw_size == null_msg->raw_size) {
@@ -1400,18 +1557,24 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Mark null message dirty */
null_msg->dirty = TRUE;
+ null_chk_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Release current chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, oh, curr_chk_proxy, curr_chk_flags) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
/* Check for gap in null message's chunk */
if(oh->chunk[old_chunkno].gap > 0) {
/* Eliminate the gap in the chunk */
- if(H5O_eliminate_gap(oh, null_msg,
+ if(H5O_eliminate_gap(f, dxpl_id, oh, null_chk_proxy, &null_chk_flags, null_msg,
((oh->chunk[old_chunkno].image + oh->chunk[old_chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[old_chunkno].gap)),
oh->chunk[old_chunkno].gap) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTREMOVE, FAIL, "can't eliminate gap in chunk")
-
- /* Set the gap size to zero for the chunk */
- oh->chunk[old_chunkno].gap = 0;
} /* end if */
+
+ /* Release null chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, oh, null_chk_proxy, null_chk_flags) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
} /* end if */
else {
unsigned new_null_msg; /* Message index for new null message */
@@ -1423,8 +1586,12 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Adjust the size of the null message being eliminated */
null_msg->raw_size = curr_msg->raw_size;
+ /* Mark null message dirty */
+ null_msg->dirty = TRUE;
+ null_chk_flags |= H5AC__DIRTIED_FLAG;
+
/* Add the gap to the chunk */
- if(H5O_add_gap(oh, null_msg->chunkno, v, null_msg->raw + null_msg->raw_size, gap_size) < 0)
+ if(H5O_add_gap(f, dxpl_id, oh, null_chk_proxy, &null_chk_flags, v, null_msg->raw + null_msg->raw_size, gap_size) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert gap in chunk")
/* Re-use message # for new null message taking place of non-null message */
@@ -1437,6 +1604,7 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Mark null message dirty */
null_msg->dirty = TRUE;
+ null_chk_flags |= H5AC__DIRTIED_FLAG;
/* Create new null message for previous location of non-null message */
if(oh->nmesgs >= oh->alloc_nmesgs) {
@@ -1451,6 +1619,10 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
new_null_msg = oh->nmesgs++;
} /* end else */
+ /* Release null message's chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, oh, null_chk_proxy, null_chk_flags) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+
/* Initialize new null message to take over non-null message's location */
oh->mesg[new_null_msg].type = H5O_MSG_NULL;
oh->mesg[new_null_msg].native = NULL;
@@ -1460,18 +1632,20 @@ H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Mark new null message dirty */
oh->mesg[new_null_msg].dirty = TRUE;
+ curr_chk_flags |= H5AC__DIRTIED_FLAG;
/* Check for gap in new null message's chunk */
if(oh->chunk[old_chunkno].gap > 0) {
/* Eliminate the gap in the chunk */
- if(H5O_eliminate_gap(oh, &oh->mesg[new_null_msg],
+ if(H5O_eliminate_gap(f, dxpl_id, oh, curr_chk_proxy, &curr_chk_flags, &oh->mesg[new_null_msg],
((oh->chunk[old_chunkno].image + oh->chunk[old_chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[old_chunkno].gap)),
oh->chunk[old_chunkno].gap) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTREMOVE, FAIL, "can't eliminate gap in chunk")
-
- /* Set the gap size to zero for the chunk */
- oh->chunk[old_chunkno].gap = 0;
} /* end if */
+
+ /* Release new null message's chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, oh, curr_chk_proxy, curr_chk_flags) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
} /* end else */
/* Indicate that we packed messages */
@@ -1520,7 +1694,7 @@ done:
*-------------------------------------------------------------------------
*/
static htri_t
-H5O_merge_null(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
+H5O_merge_null(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
{
hbool_t merged_msg; /* Flag to indicate that messages were merged */
hbool_t did_merging = FALSE; /* Whether any messages were merged */
@@ -1554,11 +1728,14 @@ H5O_merge_null(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Loop over messages again, looking for null message in same chunk */
for(v = 0, curr_msg2 = &oh->mesg[0]; v < oh->nmesgs; v++, curr_msg2++) {
if(u != v && H5O_NULL_ID == curr_msg2->type->id && curr_msg->chunkno == curr_msg2->chunkno) {
+ ssize_t adj_raw; /* Amount to adjust raw message pointer */
+ size_t adj_raw_size; /* Amount to adjust raw message size */
/* Check for second message after first message */
if((curr_msg->raw + curr_msg->raw_size) == (curr_msg2->raw - H5O_SIZEOF_MSGHDR_OH(oh))) {
/* Extend first null message length to cover second null message */
- curr_msg->raw_size += (H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg2->raw_size);
+ adj_raw = 0;
+ adj_raw_size = H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg2->raw_size;
/* Message has been merged */
merged_msg = TRUE;
@@ -1566,8 +1743,8 @@ H5O_merge_null(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Check for second message before first message */
else if((curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh)) == (curr_msg2->raw + curr_msg2->raw_size)) {
/* Adjust first message address and extend length to cover second message */
- curr_msg->raw -= (H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg2->raw_size);
- curr_msg->raw_size += (H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg2->raw_size);
+ adj_raw = -((ssize_t)(H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg2->raw_size));
+ adj_raw_size = H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg2->raw_size;
/* Message has been merged */
merged_msg = TRUE;
@@ -1575,12 +1752,26 @@ H5O_merge_null(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Second message has been merged, delete it */
if(merged_msg) {
+ H5O_chunk_proxy_t *curr_chk_proxy; /* Chunk that message is in */
+
/* Release any information/memory for second message */
H5O_msg_free_mesg(curr_msg2);
+ /* Protect chunk */
+ if(NULL == (curr_chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, curr_msg->chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
+ /* Adjust first message address and extend length to cover second message */
+ curr_msg->raw += adj_raw;
+ curr_msg->raw_size += adj_raw_size;
+
/* Mark first message as dirty */
curr_msg->dirty = TRUE;
+ /* Release new null message's chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, oh, curr_chk_proxy, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+
/* Remove second message from list of messages */
if(v < (oh->nmesgs - 1))
HDmemmove(&oh->mesg[v], &oh->mesg[v + 1], ((oh->nmesgs - 1) - v) * sizeof(H5O_mesg_t));
@@ -1591,7 +1782,7 @@ H5O_merge_null(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* If the merged message is too large, shrink the chunk */
if(curr_msg->raw_size >= H5O_MESG_MAX_SIZE)
- if(H5O_alloc_shrink_chunk(f, oh, dxpl_id, curr_msg->chunkno) < 0)
+ if(H5O_alloc_shrink_chunk(f, dxpl_id, oh, curr_msg->chunkno) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "unable to shrink chunk")
/* Get out of loop */
@@ -1676,6 +1867,20 @@ H5O_remove_empty_chunks(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
/* Decode current continuation message if necessary */
H5O_LOAD_NATIVE(f, dxpl_id, 0, oh, cont_msg, FAIL)
+ /* Check if the chunkno needs to be set */
+ /* (should only occur when the continuation message is first decoded) */
+ if(0 == ((H5O_cont_t *)(cont_msg->native))->chunkno) {
+ unsigned w; /* Local index variable */
+
+ /* Find chunk that this continuation message points to */
+ for(w = 0; w < oh->nchunks; w++)
+ if(oh->chunk[w].addr == ((H5O_cont_t *)(cont_msg->native))->addr) {
+ ((H5O_cont_t *)(cont_msg->native))->chunkno = w;
+ break;
+ } /* end if */
+ HDassert(((H5O_cont_t *)(cont_msg->native))->chunkno > 0);
+ } /* end if */
+
/* Check for correct chunk to delete */
if(oh->chunk[null_msg->chunkno].addr == ((H5O_cont_t *)(cont_msg->native))->addr)
break;
@@ -1684,6 +1889,7 @@ H5O_remove_empty_chunks(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
/* Must be a continuation message that points to chunk containing null message */
HDassert(v < oh->nmesgs);
HDassert(cont_msg);
+ HDassert(((H5O_cont_t *)(cont_msg->native))->chunkno == null_msg->chunkno);
/* Initialize information about null message */
null_msg_no = u;
@@ -1698,12 +1904,28 @@ H5O_remove_empty_chunks(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
*/
/* Free memory for chunk image */
- (void)H5FL_BLK_FREE(chunk_image, oh->chunk[null_msg->chunkno].image);
+ oh->chunk[null_msg->chunkno].image = H5FL_BLK_FREE(chunk_image, oh->chunk[null_msg->chunkno].image);
/* Remove chunk from list of chunks */
- if(null_msg->chunkno < (oh->nchunks - 1))
+ if(null_msg->chunkno < (oh->nchunks - 1)) {
HDmemmove(&oh->chunk[null_msg->chunkno], &oh->chunk[null_msg->chunkno + 1], ((oh->nchunks - 1) - null_msg->chunkno) * sizeof(H5O_chunk_t));
+ /* Adjust chunk number for any chunk proxies that are in the cache */
+ for(u = null_msg->chunkno; u < (oh->nchunks - 1); u++) {
+ unsigned chk_proxy_status = 0; /* Metadata cache status of chunk proxy for chunk */
+
+ /* Check the chunk proxy's status in the metadata cache */
+ if(H5AC_get_entry_status(f, oh->chunk[u].addr, &chk_proxy_status) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to check metadata cache status for chunk proxy")
+
+ /* If the entry is in the cache, update its chunk index */
+ if(chk_proxy_status & H5AC_ES__IN_CACHE) {
+ if(H5O_chunk_update_idx(f, dxpl_id, oh, u) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to update index for chunk proxy")
+ } /* end if */
+ } /* end for */
+ } /* end if */
+
/* Decrement # of chunks */
/* (Don't bother reducing size of chunk array for now -QAK) */
oh->nchunks--;
@@ -1737,9 +1959,24 @@ H5O_remove_empty_chunks(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
/* Decode current continuation message if necessary */
H5O_LOAD_NATIVE(f, dxpl_id, 0, oh, curr_msg, FAIL)
- /* Check for pointer to chunk after deleted chunk */
- if(((H5O_cont_t *)(curr_msg->native))->chunkno > deleted_chunkno)
- ((H5O_cont_t *)(curr_msg->native))->chunkno--;
+ /* Check if the chunkno needs to be set */
+ /* (should only occur when the continuation message is first decoded) */
+ if(0 == ((H5O_cont_t *)(curr_msg->native))->chunkno) {
+ unsigned w; /* Local index variable */
+
+ /* Find chunk that this continuation message points to */
+ for(w = 0; w < oh->nchunks; w++)
+ if(oh->chunk[w].addr == ((H5O_cont_t *)(curr_msg->native))->addr) {
+ ((H5O_cont_t *)(curr_msg->native))->chunkno = w;
+ break;
+ } /* end if */
+ HDassert(((H5O_cont_t *)(curr_msg->native))->chunkno > 0);
+ } /* end if */
+ else {
+ /* Check for pointer to chunk after deleted chunk */
+ if(((H5O_cont_t *)(curr_msg->native))->chunkno > deleted_chunkno)
+ ((H5O_cont_t *)(curr_msg->native))->chunkno--;
+ } /* end else */
} /* end if */
} /* end for */
@@ -1799,14 +2036,14 @@ H5O_condense_header(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
rescan_header = FALSE;
/* Scan for messages that can be moved earlier in chunks */
- result = H5O_move_msgs_forward(f, oh, dxpl_id);
+ result = H5O_move_msgs_forward(f, dxpl_id, oh);
if(result < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't move header messages forward")
if(result > 0)
rescan_header = TRUE;
/* Scan for adjacent null messages & merge them */
- result = H5O_merge_null(f, oh, dxpl_id);
+ result = H5O_merge_null(f, dxpl_id, oh);
if(result < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't pack null header messages")
if(result > 0)
@@ -1843,13 +2080,11 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_alloc_shrink_chunk(H5F_t *f,
- H5O_t *oh,
- hid_t dxpl_id,
- unsigned chunkno)
+H5O_alloc_shrink_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned chunkno)
{
H5O_chunk_t *chunk = &oh->chunk[chunkno]; /* Chunk to shrink */
- H5O_mesg_t *curr_msg;
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Metadata cache proxy for chunk to shrink */
+ H5O_mesg_t *curr_msg; /* Current message to examine */
uint8_t *old_image = chunk->image; /* Old address of chunk's image in memory */
size_t old_size = chunk->size; /* Old size of chunk */
size_t new_size = chunk->size - chunk->gap; /* Size of shrunk chunk */
@@ -1866,20 +2101,25 @@ H5O_alloc_shrink_chunk(H5F_t *f,
FUNC_ENTER_NOAPI_NOINIT(H5O_alloc_shrink_chunk)
/* check args */
- HDassert(f != NULL);
+ HDassert(f);
+ HDassert(oh);
+
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header chunk")
/* Loop backwards to increase the chance of seeing more null messages at the
* end of the chunk. Note that we rely on unsigned u wrapping around at the
* end.
*/
- for (u = oh->nmesgs - 1, curr_msg = &oh->mesg[u]; u < oh->nmesgs; u--, curr_msg--) {
- if ((H5O_NULL_ID == curr_msg->type->id) && (chunkno == curr_msg->chunkno)) {
+ for(u = oh->nmesgs - 1, curr_msg = &oh->mesg[u]; u < oh->nmesgs; u--, curr_msg--) {
+ if((H5O_NULL_ID == curr_msg->type->id) && (chunkno == curr_msg->chunkno)) {
size_t shrink_size = curr_msg->raw_size + sizeof_msghdr; /* Amount to shrink the chunk by */
/* If the current message is not at the end of the chunk, copy the
* data after it (except the checksum).
*/
- if (curr_msg->raw + curr_msg->raw_size
+ if(curr_msg->raw + curr_msg->raw_size
< old_image + new_size - sizeof_chksum) {
unsigned v; /* Index */
H5O_mesg_t *curr_msg2;
@@ -1890,8 +2130,8 @@ H5O_alloc_shrink_chunk(H5F_t *f,
(size_t)(old_image + new_size - sizeof_chksum - src));
/* Update the raw data pointers for messages after this one */
- for (v = 0, curr_msg2 = &oh->mesg[0]; v < oh->nmesgs; v++, curr_msg2++)
- if ((chunkno == curr_msg2->chunkno) && (curr_msg2->raw > curr_msg->raw))
+ for(v = 0, curr_msg2 = &oh->mesg[0]; v < oh->nmesgs; v++, curr_msg2++)
+ if((chunkno == curr_msg2->chunkno) && (curr_msg2->raw > curr_msg->raw))
curr_msg2->raw -= shrink_size;
} /* end if */
@@ -1902,7 +2142,7 @@ H5O_alloc_shrink_chunk(H5F_t *f,
H5O_msg_free_mesg(curr_msg);
/* Remove the deleted null message from list of messages */
- if (u < (oh->nmesgs - 1))
+ if(u < (oh->nmesgs - 1))
HDmemmove(&oh->mesg[u], &oh->mesg[u+1], ((oh->nmesgs - 1) - u) * sizeof(H5O_mesg_t));
/* Decrement # of messages */
@@ -1928,7 +2168,7 @@ H5O_alloc_shrink_chunk(H5F_t *f,
/* update the new chunk size */
new_size += oh->mesg[oh->nmesgs].raw_size + sizeof_msghdr;
- }
+ } /* end if */
/* Check for changing the chunk #0 data size enough to need adjusting the flags */
if(oh->version > H5O_VERSION_1 && chunkno == 0) {
@@ -1936,19 +2176,19 @@ H5O_alloc_shrink_chunk(H5F_t *f,
size_t orig_prfx_size = 1 << (oh->flags & H5O_HDR_CHUNK0_SIZE); /* Original prefix size */
/* Check for moving to a 1-byte size encoding */
- if (orig_prfx_size > 1 && chunk0_newsize <= 255) {
+ if(orig_prfx_size > 1 && chunk0_newsize <= 255) {
less_prfx_size = orig_prfx_size - 1;
new_size_flags = H5O_HDR_CHUNK0_1;
adjust_size_flags = TRUE;
} /* end if */
/* Check for moving to a 2-byte size encoding */
- else if (orig_prfx_size > 2 && chunk0_newsize <= 65535) {
+ else if(orig_prfx_size > 2 && chunk0_newsize <= 65535) {
less_prfx_size = orig_prfx_size - 2;
new_size_flags = H5O_HDR_CHUNK0_2;
adjust_size_flags = TRUE;
} /* end if */
/* Check for moving to a 4-byte size encoding */
- else if (orig_prfx_size > 4 && chunk0_newsize <= 4294967295) {
+ else if(orig_prfx_size > 4 && chunk0_newsize <= 4294967295) {
less_prfx_size = orig_prfx_size - 4;
new_size_flags = H5O_HDR_CHUNK0_4;
adjust_size_flags = TRUE;
@@ -1973,38 +2213,51 @@ H5O_alloc_shrink_chunk(H5F_t *f,
chunk->size = new_size;
chunk->image = H5FL_BLK_REALLOC(chunk_image, old_image, chunk->size);
chunk->gap = 0;
- chunk->dirty = TRUE;
- if (NULL == oh->chunk[chunkno].image)
+ if(NULL == oh->chunk[chunkno].image)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Spin through existing messages, adjusting them */
- for (u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
- if (adjust_size_flags || (chunk->image != old_image))
+ for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
+ if(adjust_size_flags || (chunk->image != old_image))
/* Adjust raw addresses for messages in this chunk to reflect new 'image' address */
- if (curr_msg->chunkno == chunkno)
+ if(curr_msg->chunkno == chunkno)
curr_msg->raw = chunk->image - less_prfx_size + (curr_msg->raw - old_image);
/* Find continuation message which points to this chunk and adjust chunk's size */
/* (Chunk 0 doesn't have a continuation message that points to it and
* its size is directly encoded in the object header) */
- if (chunkno > 0 && (H5O_CONT_ID == curr_msg->type->id) &&
- (((H5O_cont_t *)(curr_msg->native))->chunkno == chunkno)) {
+ if(chunkno > 0 && (H5O_CONT_ID == curr_msg->type->id) &&
+ (((H5O_cont_t *)(curr_msg->native))->chunkno == chunkno)) {
+ H5O_chunk_proxy_t *cont_chk_proxy; /* Chunk that message is in */
+
+ /* Protect chunk */
+ if(NULL == (cont_chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, curr_msg->chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header chunk")
+
/* Adjust size of continuation message */
HDassert(((H5O_cont_t *)(curr_msg->native))->size == old_size);
((H5O_cont_t *)(curr_msg->native))->size = chunk->size;
/* Flag continuation message as dirty */
curr_msg->dirty = TRUE;
+
+ /* Release chunk, marking it dirty */
+ if(H5O_chunk_unprotect(f, dxpl_id, oh, cont_chk_proxy, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
} /* end if */
} /* end for */
HDassert(new_size <= old_size);
/* Free the unused space in the file */
- if (H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, chunk->addr + new_size, (hsize_t)(old_size - new_size)) < 0)
+ if(H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, chunk->addr + new_size, (hsize_t)(old_size - new_size)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to shrink object header chunk")
done:
+ /* Release chunk, marking it dirty */
+ if(chk_proxy && H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy, H5AC__DIRTIED_FLAG) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_alloc_shrink_chunk() */
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index 72f02df..bfa9ba0 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -223,7 +223,6 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
H5O_ainfo_t ainfo; /* Attribute information for object */
- unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
herr_t ret_value = SUCCEED; /* Return value */
@@ -233,9 +232,9 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
HDassert(loc);
HDassert(attr);
- /* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
+ /* Pin the object header */
+ if(NULL == (oh = H5O_pin(loc, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin object header")
/* Check if this object already has attribute information */
if(oh->version > H5O_VERSION_1) {
@@ -396,12 +395,9 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
- /* Indicate that the object header was modified */
- oh_flags |= H5AC__DIRTIED_FLAG;
-
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_create() */
@@ -487,7 +483,7 @@ H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
HDassert(name);
/* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, NULL, "unable to load object header")
/* Check for attribute info stored */
@@ -544,7 +540,7 @@ H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
} /* end else */
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -628,7 +624,7 @@ H5O_attr_open_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, NULL, "can't locate attribute")
/* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, NULL, "unable to load object header")
/* Find out whether it has already been opened. If it has, close the object
@@ -654,7 +650,7 @@ H5O_attr_open_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
} /* end if */
done:
- if(oh && H5AC_unprotect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -836,6 +832,8 @@ H5O_attr_write_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
unsigned UNUSED sequence, hbool_t *oh_modified, void *_udata/*in,out*/)
{
H5O_iter_wrt_t *udata = (H5O_iter_wrt_t *)_udata; /* Operator user data */
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */
+ unsigned chk_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting chunk */
herr_t ret_value = H5_ITER_CONT; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_write_cb)
@@ -847,14 +845,35 @@ H5O_attr_write_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* Check for correct attribute message to modify */
if(0 == HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->attr->shared->name)) {
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(udata->f, udata->dxpl_id, oh, mesg->chunkno)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, H5_ITER_ERROR, "unable to load object header chunk")
+
+ /* Allocate storage for the message's data, if necessary */
+ if(NULL == ((H5A_t *)mesg->native)->shared->data)
+ if(NULL == (((H5A_t *)mesg->native)->shared->data = H5FL_BLK_MALLOC(attr_buf, udata->attr->shared->data_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed")
+
+ /* Copy the data into the header message */
+ /* (Needs to occur before updating the shared message, or the hash
+ * value on the old & new messages will be the same)
+ */
+ HDmemcpy(((H5A_t *)mesg->native)->shared->data, udata->attr->shared->data, udata->attr->shared->data_size);
+
+ /* Mark the message as modified */
+ mesg->dirty = TRUE;
+ chk_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Release chunk */
+ if(H5O_chunk_unprotect(udata->f, udata->dxpl_id, oh, chk_proxy, chk_flags) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, H5_ITER_ERROR, "unable to unprotect object header chunk")
+ chk_proxy = NULL;
+
/* Update the shared attribute in the SOHM storage */
if(mesg->flags & H5O_MSG_FLAG_SHARED)
if(H5O_attr_update_shared(udata->f, udata->dxpl_id, oh, udata->attr, (H5O_shared_t *)mesg->native) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, H5_ITER_ERROR, "unable to update attribute in shared storage")
- /* Mark message as dirty */
- mesg->dirty = TRUE;
-
/* Indicate that the object header was modified */
*oh_modified = TRUE;
@@ -866,6 +885,10 @@ H5O_attr_write_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
} /* end if */
done:
+ /* Release chunk, if not already done */
+ if(chk_proxy && H5O_chunk_unprotect(udata->f, udata->dxpl_id, oh, chk_proxy, chk_flags) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, H5_ITER_ERROR, "unable to unprotect object header chunk")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_write_cb() */
@@ -887,7 +910,6 @@ H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
{
H5O_t *oh = NULL; /* Pointer to actual object header */
H5O_ainfo_t ainfo; /* Attribute information for object */
- unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_write)
@@ -896,9 +918,9 @@ H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
HDassert(loc);
HDassert(attr);
- /* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
+ /* Pin the object header */
+ if(NULL == (oh = H5O_pin(loc, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin object header")
/* Check for attribute info stored */
ainfo.fheap_addr = HADDR_UNDEF;
@@ -939,12 +961,9 @@ H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
- /* Indicate that the object header was modified */
- oh_flags |= H5AC__DIRTIED_FLAG;
-
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_write */
@@ -1015,6 +1034,8 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
unsigned UNUSED sequence, hbool_t *oh_modified, void *_udata/*in,out*/)
{
H5O_iter_ren_t *udata = (H5O_iter_ren_t *)_udata; /* Operator user data */
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */
+ unsigned chk_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting chunk */
herr_t ret_value = H5_ITER_CONT; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename_mod_cb)
@@ -1028,6 +1049,10 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->old_name) == 0) {
unsigned old_version = ((H5A_t *)mesg->native)->shared->version; /* Old version of the attribute */
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(udata->f, udata->dxpl_id, oh, mesg->chunkno)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, H5_ITER_ERROR, "unable to load object header chunk")
+
/* Change the name for the attribute */
H5MM_xfree(((H5A_t *)mesg->native)->shared->name);
((H5A_t *)mesg->native)->shared->name = H5MM_xstrdup(udata->new_name);
@@ -1038,6 +1063,12 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* Mark the message as modified */
mesg->dirty = TRUE;
+ chk_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Release chunk */
+ if(H5O_chunk_unprotect(udata->f, udata->dxpl_id, oh, chk_proxy, chk_flags) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, H5_ITER_ERROR, "unable to unprotect object header chunk")
+ chk_proxy = NULL;
/* Check for shared message */
if(mesg->flags & H5O_MSG_FLAG_SHARED) {
@@ -1098,6 +1129,10 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
} /* end if */
done:
+ /* Release chunk, if not already done */
+ if(chk_proxy && H5O_chunk_unprotect(udata->f, udata->dxpl_id, oh, chk_proxy, chk_flags) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, H5_ITER_ERROR, "unable to unprotect object header chunk")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_rename_mod_cb() */
@@ -1120,7 +1155,6 @@ H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name,
{
H5O_t *oh = NULL; /* Pointer to actual object header */
H5O_ainfo_t ainfo; /* Attribute information for object */
- unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename)
@@ -1130,9 +1164,9 @@ H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name,
HDassert(old_name);
HDassert(new_name);
- /* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
+ /* Pin the object header */
+ if(NULL == (oh = H5O_pin(loc, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin object header")
/* Check for attribute info stored */
ainfo.fheap_addr = HADDR_UNDEF;
@@ -1184,12 +1218,9 @@ H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name,
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
- /* Indicate that the object header was modified */
- oh_flags |= H5AC__DIRTIED_FLAG;
-
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_rename */
@@ -1226,7 +1257,7 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
HDassert(attr_op);
/* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -1244,7 +1275,7 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
/* Release the object header */
- if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
oh = NULL;
@@ -1258,7 +1289,7 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
/* Release the object header */
- if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
oh = NULL;
@@ -1273,7 +1304,7 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
done:
/* Release resources */
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
if(atable.attrs && H5A_attr_release_table(&atable) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
@@ -1511,7 +1542,6 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
H5O_t *oh = NULL; /* Pointer to actual object header */
H5O_ainfo_t ainfo; /* Attribute information for object */
htri_t ainfo_exists = FALSE; /* Whether the attribute info exists in the file */
- unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_remove)
@@ -1520,9 +1550,9 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
HDassert(loc);
HDassert(name);
- /* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
+ /* Pin the object header */
+ if(NULL == (oh = H5O_pin(loc, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin object header")
/* Check for attribute info stored */
ainfo.fheap_addr = HADDR_UNDEF;
@@ -1568,12 +1598,9 @@ H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
- /* Indicate that the object header was modified */
- oh_flags |= H5AC__DIRTIED_FLAG;
-
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_remove() */
@@ -1599,7 +1626,6 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
H5O_t *oh = NULL; /* Pointer to actual object header */
H5O_ainfo_t ainfo; /* Attribute information for object */
htri_t ainfo_exists = FALSE; /* Whether the attribute info exists in the file */
- unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1608,9 +1634,9 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
/* Check arguments */
HDassert(loc);
- /* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
+ /* Pin the object header */
+ if(NULL == (oh = H5O_pin(loc, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin object header")
/* Check for attribute info stored */
ainfo.fheap_addr = HADDR_UNDEF;
@@ -1664,12 +1690,9 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
- /* Indicate that the object header was modified */
- oh_flags |= H5AC__DIRTIED_FLAG;
-
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
if(atable.attrs && H5A_attr_release_table(&atable) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
@@ -1797,7 +1820,7 @@ H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
HDassert(name);
/* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -1835,7 +1858,7 @@ H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
} /* end else */
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1951,7 +1974,7 @@ H5O_attr_count(const H5O_loc_t *loc, hid_t dxpl_id)
HDassert(loc);
/* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Retrieve # of attributes on object */
@@ -1962,7 +1985,7 @@ H5O_attr_count(const H5O_loc_t *loc, hid_t dxpl_id)
ret_value = (int)nattrs;
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index 780d5bb..95f3d3a 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -39,6 +39,7 @@
#include "H5FLprivate.h" /* Free lists */
#include "H5MFprivate.h" /* File memory management */
#include "H5Opkg.h" /* Object headers */
+#include "H5WBprivate.h" /* Wrapped Buffers */
/****************/
@@ -74,25 +75,31 @@ static herr_t H5O_dest(H5F_t *f, H5O_t *oh);
static herr_t H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy);
static herr_t H5O_size(const H5F_t *f, const H5O_t *oh, size_t *size_ptr);
+static H5O_chunk_proxy_t *H5O_cache_chk_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1,
+ void *_udata2);
+static herr_t H5O_cache_chk_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_chunk_proxy_t *chk_proxy, unsigned UNUSED * flags_ptr);
+static herr_t H5O_cache_chk_dest(H5F_t *f, H5O_chunk_proxy_t *chk_proxy);
+static herr_t H5O_cache_chk_clear(H5F_t *f, H5O_chunk_proxy_t *chk_proxy, hbool_t destroy);
+static herr_t H5O_cache_chk_size(const H5F_t *f, const H5O_chunk_proxy_t *chk_proxy, size_t *size_ptr);
-/*********************/
-/* Package Variables */
-/*********************/
-
+/* Chunk proxy routines */
+static herr_t H5O_chunk_proxy_dest(H5O_chunk_proxy_t *chunk_proxy);
-/*****************************/
-/* Library Private Variables */
-/*****************************/
+/* Chunk routines */
+static herr_t H5O_chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len,
+ const uint8_t *image, H5O_common_cache_ud_t *udata, hbool_t *dirty);
+static herr_t H5O_chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno);
-/* Declare external the free list for H5O_unknown_t's */
-H5FL_EXTERN(H5O_unknown_t);
+/* Misc. routines */
+static herr_t H5O_add_cont_msg(H5O_cont_msgs_t *cont_msg_info,
+ const H5O_cont_t *cont);
-/*******************/
-/* Local Variables */
-/*******************/
+/*********************/
+/* Package Variables */
+/*********************/
-/* H5O inherits cache-like properties from H5AC */
+/* H5O object header prefix inherits cache-like properties from H5AC */
const H5AC_class_t H5AC_OHDR[1] = {{
H5AC_OHDR_ID,
(H5AC_load_func_t)H5O_load,
@@ -103,6 +110,37 @@ const H5AC_class_t H5AC_OHDR[1] = {{
(H5AC_size_func_t)H5O_size,
}};
+/* H5O object header chunk inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_OHDR_CHK[1] = {{
+ H5AC_OHDR_CHK_ID,
+ (H5AC_load_func_t)H5O_cache_chk_load,
+ (H5AC_flush_func_t)H5O_cache_chk_flush,
+ (H5AC_dest_func_t)H5O_cache_chk_dest,
+ (H5AC_clear_func_t)H5O_cache_chk_clear,
+ (H5AC_notify_func_t)NULL,
+ (H5AC_size_func_t)H5O_cache_chk_size,
+}};
+
+/* Declare external the free list for H5O_unknown_t's */
+H5FL_EXTERN(H5O_unknown_t);
+
+/* Declare extern the free list for H5O_chunk_proxy_t's */
+H5FL_EXTERN(H5O_chunk_proxy_t);
+
+/* Declare the free list for H5O_cont_t sequences */
+H5FL_SEQ_DEFINE(H5O_cont_t);
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
/*-------------------------------------------------------------------------
* Function: H5O_load
@@ -121,18 +159,17 @@ const H5AC_class_t H5AC_OHDR[1] = {{
*/
static H5O_t *
H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
- void UNUSED * _udata2)
+ void *_udata2)
{
H5O_t *oh = NULL; /* Object header read in */
+ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata2; /* User data for callback */
+ H5WB_t *wb = NULL; /* Wrapped buffer for prefix data */
uint8_t read_buf[H5O_SPEC_READ_SIZE]; /* Buffer for speculative read */
const uint8_t *p; /* Pointer into buffer to decode */
+ uint8_t *buf; /* Buffer to decode */
size_t spec_read_size; /* Size of buffer to speculatively read in */
size_t prefix_size; /* Size of object header prefix */
- unsigned nmesgs; /* Total # of messages in this object header */
- unsigned curmesg = 0; /* Current message being decoded in object header */
- unsigned merged_null_msgs = 0; /* Number of null messages merged together */
- haddr_t chunk_addr; /* Address of first chunk */
- size_t chunk_size; /* Size of first chunk */
+ size_t buf_size; /* Size of prefix+chunk #0 buffer */
haddr_t eoa; /* Relative end of file address */
H5O_t *ret_value; /* Return value */
@@ -142,7 +179,9 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
HDassert(f);
HDassert(H5F_addr_defined(addr));
HDassert(!_udata1);
- HDassert(!_udata2);
+ HDassert(udata);
+ HDassert(udata->common.f);
+ HDassert(udata->common.cont_msg_info);
/* Make certain we don't speculatively read off the end of the file */
if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_OHDR)))
@@ -161,8 +200,8 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* File-specific, non-stored information */
- oh->sizeof_size = H5F_SIZEOF_SIZE(f);
- oh->sizeof_addr = H5F_SIZEOF_ADDR(f);
+ oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f);
+ oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f);
/* Check for presence of magic number */
/* (indicates version 2 or later) */
@@ -180,9 +219,6 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
if(oh->flags & ~H5O_HDR_ALL_FLAGS)
HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "unknown object header status flag(s)")
- /* Number of messages (to allocate initially) */
- nmesgs = 1;
-
/* Number of links to object (unless overridden by refcount message) */
oh->nlink = 1;
@@ -207,7 +243,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
UINT16DECODE(p, oh->max_compact);
UINT16DECODE(p, oh->min_dense);
if(oh->max_compact < oh->min_dense)
- HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header attribute phase change values")
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header attribute phase change values")
} /* end if */
else {
oh->max_compact = H5O_CRT_ATTR_MAX_COMPACT_DEF;
@@ -217,26 +253,26 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* First chunk size */
switch(oh->flags & H5O_HDR_CHUNK0_SIZE) {
case 0: /* 1 byte size */
- chunk_size = *p++;
+ oh->chunk0_size = *p++;
break;
case 1: /* 2 byte size */
- UINT16DECODE(p, chunk_size);
+ UINT16DECODE(p, oh->chunk0_size);
break;
case 2: /* 4 byte size */
- UINT32DECODE(p, chunk_size);
+ UINT32DECODE(p, oh->chunk0_size);
break;
case 3: /* 8 byte size */
- UINT64DECODE(p, chunk_size);
+ UINT64DECODE(p, oh->chunk0_size);
break;
default:
HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad size for chunk 0")
} /* end switch */
- if(chunk_size > 0 && chunk_size < H5O_SIZEOF_MSGHDR_OH(oh))
- HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header chunk size")
+ if(oh->chunk0_size > 0 && oh->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header chunk size")
} /* end if */
else {
/* Version */
@@ -251,7 +287,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
p++;
/* Number of messages */
- UINT16DECODE(p, nmesgs);
+ UINT16DECODE(p, udata->v1_pfx_nmesgs);
/* Link count */
UINT32DECODE(p, oh->nlink);
@@ -264,10 +300,10 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
oh->min_dense = 0;
/* First chunk size */
- UINT32DECODE(p, chunk_size);
- if((nmesgs > 0 && chunk_size < H5O_SIZEOF_MSGHDR_OH(oh)) ||
- (nmesgs == 0 && chunk_size > 0))
- HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header chunk size")
+ UINT32DECODE(p, oh->chunk0_size);
+ if((udata->v1_pfx_nmesgs > 0 && oh->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) ||
+ (udata->v1_pfx_nmesgs == 0 && oh->chunk0_size > 0))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header chunk size")
/* Reserved, in version 1 (for 8-byte alignment padding) */
p += 4;
@@ -277,356 +313,44 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
prefix_size = (size_t)(p - (const uint8_t *)read_buf);
HDassert((size_t)prefix_size == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
- /* Compute first chunk address */
- chunk_addr = addr + (hsize_t)prefix_size;
+ /* Compute the size of the buffer used */
+ buf_size = oh->chunk0_size + (size_t)H5O_SIZEOF_HDR(oh);
- /* Allocate the message array */
- oh->alloc_nmesgs = (nmesgs > 0) ? nmesgs : 1;
- if(NULL == (oh->mesg = H5FL_SEQ_MALLOC(H5O_mesg_t, oh->alloc_nmesgs)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed")
-
- /* Read each chunk from disk */
- while(H5F_addr_defined(chunk_addr)) {
- unsigned chunkno; /* Current chunk's index */
-#ifndef NDEBUG
- unsigned nullcnt; /* Count of null messages (for sanity checking gaps in chunks) */
-#endif /* NDEBUG */
- uint8_t *eom_ptr; /* Pointer to end of messages for a chunk */
-
- /* Increase chunk array size, if necessary */
- if(oh->nchunks >= oh->alloc_nchunks) {
- unsigned na = MAX(H5O_NCHUNKS, oh->alloc_nchunks * 2); /* Double # of chunks allocated */
- H5O_chunk_t *x = H5FL_SEQ_REALLOC(H5O_chunk_t, oh->chunk, (size_t)na);
-
- if(!x)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed")
- oh->alloc_nchunks = na;
- oh->chunk = x;
- } /* end if */
-
- /* Init the chunk data info */
- chunkno = oh->nchunks++;
- oh->chunk[chunkno].dirty = FALSE;
- oh->chunk[chunkno].gap = 0;
- if(chunkno == 0) {
- /* First chunk's 'image' includes room for the object header prefix */
- oh->chunk[0].addr = addr;
- oh->chunk[0].size = chunk_size + H5O_SIZEOF_HDR(oh);
- } /* end if */
- else {
- oh->chunk[chunkno].addr = chunk_addr;
- oh->chunk[chunkno].size = chunk_size;
- } /* end else */
- if(NULL == (oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, oh->chunk[chunkno].size)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed")
-
- /* Handle chunk 0 as special case */
- if(chunkno == 0) {
- /* Check for speculative read of first chunk containing all the data needed */
- if(spec_read_size >= oh->chunk[0].size)
- HDmemcpy(oh->chunk[0].image, read_buf, oh->chunk[0].size);
- else {
- /* Copy the object header prefix into chunk 0's image */
- HDmemcpy(oh->chunk[0].image, read_buf, prefix_size);
-
- /* Read the chunk raw data */
- /* (probably re-reads some data we already retrieved, but since
- * we have to do the I/O operation anyway, we might as
- * well avoid memcpy()ing the data in our buffer already)
- */
- if(H5F_block_read(f, H5FD_MEM_OHDR, chunk_addr, (oh->chunk[0].size - prefix_size),
- dxpl_id, (oh->chunk[0].image + prefix_size)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data")
- } /* end else */
-
- /* Point into chunk image to decode */
- p = oh->chunk[0].image + prefix_size;
- } /* end if */
- else {
- /* Read the chunk raw data */
- if(H5F_block_read(f, H5FD_MEM_OHDR, chunk_addr, chunk_size, dxpl_id, oh->chunk[chunkno].image) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data")
+ /* Check if the speculative read was large enough to parse the first chunk */
+ if(spec_read_size < buf_size) {
+ /* Wrap the local buffer for serialized header info */
+ if(NULL == (wb = H5WB_wrap(read_buf, sizeof(read_buf))))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't wrap buffer")
- /* Point into chunk image to decode */
- p = oh->chunk[chunkno].image;
- } /* end else */
+ /* Get a pointer to a buffer that's large enough for serialized header */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, buf_size)))
+ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't get actual buffer")
- /* Check for magic # on chunks > 0 in later versions of the format */
- if(chunkno > 0 && oh->version > H5O_VERSION_1) {
- /* Magic number */
- if(HDmemcmp(p, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "wrong object header chunk signature")
- p += H5_SIZEOF_MAGIC;
- } /* end if */
+ /* Copy existing raw data into new buffer */
+ HDmemcpy(buf, read_buf, spec_read_size);
- /* Decode messages from this chunk */
- eom_ptr = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh));
-#ifndef NDEBUG
- nullcnt = 0;
-#endif /* NDEBUG */
- while(p < eom_ptr) {
- unsigned mesgno; /* Current message to operate on */
- size_t mesg_size; /* Size of message read in */
- unsigned id; /* ID (type) of current message */
- uint8_t flags; /* Flags for current message */
- H5O_msg_crt_idx_t crt_idx = 0; /* Creation index for current message */
-
- /* Decode message prefix info */
-
- /* Version # */
- if(oh->version == H5O_VERSION_1)
- UINT16DECODE(p, id)
- else
- id = *p++;
-
- /* Check for unknown message ID getting encoded in file */
- if(id == H5O_UNKNOWN_ID)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "'unknown' message ID encoded in file?!?")
-
- /* Message size */
- UINT16DECODE(p, mesg_size);
- HDassert(mesg_size == H5O_ALIGN_OH(oh, mesg_size));
-
- /* Message flags */
- flags = *p++;
- if(flags & ~H5O_MSG_FLAG_BITS)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unknown flag for message")
- if((flags & H5O_MSG_FLAG_SHARED) && (flags & H5O_MSG_FLAG_DONTSHARE))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad flag combination for message")
- if((flags & H5O_MSG_FLAG_WAS_UNKNOWN) && (flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad flag combination for message")
- if((flags & H5O_MSG_FLAG_WAS_UNKNOWN) && !(flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad flag combination for message")
-
- /* Reserved bytes/creation index */
- if(oh->version == H5O_VERSION_1)
- p += 3; /*reserved*/
- else {
- /* Only decode creation index if they are being tracked */
- if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
- UINT16DECODE(p, crt_idx);
- } /* end else */
-
- /* Try to detect invalidly formatted object header message that
- * extends past end of chunk.
- */
- if(p + mesg_size > eom_ptr)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "corrupt object header")
-
-#ifndef NDEBUG
- /* Increment count of null messages */
- if(H5O_NULL_ID == id)
- nullcnt++;
-#endif /* NDEBUG */
-
- /* Check for combining two adjacent 'null' messages */
- if((H5F_INTENT(f) & H5F_ACC_RDWR) &&
- H5O_NULL_ID == id && oh->nmesgs > 0 &&
- H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id &&
- oh->mesg[oh->nmesgs - 1].chunkno == chunkno) {
-
- /* Combine adjacent null messages */
- mesgno = oh->nmesgs - 1;
- oh->mesg[mesgno].raw_size += H5O_SIZEOF_MSGHDR_OH(oh) + mesg_size;
- oh->mesg[mesgno].dirty = TRUE;
- merged_null_msgs++;
- } /* end if */
- else {
- /* Check if we need to extend message table to hold the new message */
- if(oh->nmesgs >= oh->alloc_nmesgs)
- if(H5O_alloc_msgs(oh, (size_t)1) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "can't allocate more space for messages")
-
- /* Get index for message */
- mesgno = oh->nmesgs++;
-
- /* Initialize information about message */
- oh->mesg[mesgno].dirty = FALSE;
- oh->mesg[mesgno].flags = flags;
- oh->mesg[mesgno].crt_idx = crt_idx;
- oh->mesg[mesgno].native = NULL;
- oh->mesg[mesgno].raw = (uint8_t *)p; /* Casting away const OK - QAK */
- oh->mesg[mesgno].raw_size = mesg_size;
- oh->mesg[mesgno].chunkno = chunkno;
-
- /* Point unknown messages at 'unknown' message class */
- /* (Usually from future versions of the library) */
- if(id >= NELMTS(H5O_msg_class_g) || NULL == H5O_msg_class_g[id]) {
- H5O_unknown_t *unknown; /* Pointer to "unknown" message info */
-
- /* Allocate "unknown" message info */
- if(NULL == (unknown = H5FL_MALLOC(H5O_unknown_t)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed")
-
- /* Save the original message type ID */
- *unknown = id;
-
- /* Save 'native' form of unknown message */
- oh->mesg[mesgno].native = unknown;
-
- /* Set message to "unknown" class */
- oh->mesg[mesgno].type = H5O_msg_class_g[H5O_UNKNOWN_ID];
-
- /* Check for "fail if unknown" message flag */
- if(flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN)
- HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "unknown message with 'fail if unknown' flag found")
- /* Check for "mark if unknown" message flag, etc. */
- else if((flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN) &&
- !(flags & H5O_MSG_FLAG_WAS_UNKNOWN) &&
- (H5F_INTENT(f) & H5F_ACC_RDWR)) {
-
- /* Mark the message as "unknown" */
- /* This is a bit aggressive, since the application may
- * never change anything about the object (metadata or
- * raw data), but we can sort out the finer details
- * when/if we start using the flag - QAK
- */
- /* Also, it's possible that this functionality may not
- * get invoked if the object header is brought into
- * the metadata cache in some other "weird" way, like
- * using H5Ocopy() - QAK
- */
- oh->mesg[mesgno].flags |= H5O_MSG_FLAG_WAS_UNKNOWN;
-
- /* Mark the message and object header as dirty */
- oh->mesg[mesgno].dirty = TRUE;
- oh->cache_info.is_dirty = TRUE;
- } /* end if */
- } /* end if */
- else
- /* Set message class for "known" messages */
- oh->mesg[mesgno].type = H5O_msg_class_g[id];
- } /* end else */
-
- /* Advance decode pointer past message */
- p += mesg_size;
-
- /* Check for 'gap' at end of chunk */
- if((eom_ptr - p) > 0 && (eom_ptr - p) < H5O_SIZEOF_MSGHDR_OH(oh)) {
- /* Gaps can only occur in later versions of the format */
- HDassert(oh->version > H5O_VERSION_1);
-
- /* Gaps should only occur in chunks with no null messages */
- HDassert(nullcnt == 0);
-
- /* Set gap information for chunk */
- oh->chunk[chunkno].gap = (size_t)(eom_ptr - p);
-
- /* Increment location in chunk */
- p += oh->chunk[chunkno].gap;
- } /* end if */
- } /* end while */
-
- /* Check for correct checksum on chunks, in later versions of the format */
- if(oh->version > H5O_VERSION_1) {
- uint32_t stored_chksum; /* Checksum from file */
- uint32_t computed_chksum; /* Checksum computed in memory */
-
- /* Metadata checksum */
- UINT32DECODE(p, stored_chksum);
-
- /* Compute checksum on chunk */
- computed_chksum = H5_checksum_metadata(oh->chunk[chunkno].image, (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM), 0);
-
- /* Verify checksum */
- if(stored_chksum != computed_chksum)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "incorrect metadata checksum for object header chunk")
- } /* end if */
-
- /* Sanity check */
- HDassert(p == oh->chunk[chunkno].image + oh->chunk[chunkno].size);
-
- /* Check for another chunk to read in & parse */
- for(chunk_addr = HADDR_UNDEF; !H5F_addr_defined(chunk_addr) && curmesg < oh->nmesgs; ++curmesg) {
- /* Check if next message to examine is a continuation message */
- if(H5O_CONT_ID == oh->mesg[curmesg].type->id) {
- H5O_cont_t *cont;
- unsigned ioflags = 0; /* Flags for decode routine */
-
- /* Decode continuation message */
- cont = (H5O_cont_t *)(H5O_MSG_CONT->decode)(f, dxpl_id, NULL, 0, &ioflags, oh->mesg[curmesg].raw);
- cont->chunkno = oh->nchunks; /*the next chunk to allocate */
-
- /* Save 'native' form of continuation message */
- oh->mesg[curmesg].native = cont;
-
- /* Set up to read in next chunk */
- chunk_addr = cont->addr;
- chunk_size = cont->size;
-
- /* Mark the object header as dirty if the message was changed by decoding */
- if((ioflags & H5O_DECODEIO_DIRTY) && (H5F_get_intent(f) & H5F_ACC_RDWR)) {
- oh->mesg[curmesg].dirty = TRUE;
- oh->cache_info.is_dirty = TRUE;
- }
- } /* end if */
- /* Check if next message to examine is a ref. count message */
- else if(H5O_REFCOUNT_ID == oh->mesg[curmesg].type->id) {
- H5O_refcount_t *refcount;
- unsigned ioflags = 0; /* Flags for decode routine */
-
- /* Decode ref. count message */
- HDassert(oh->version > H5O_VERSION_1);
- refcount = (H5O_refcount_t *)(H5O_MSG_REFCOUNT->decode)(f, dxpl_id, NULL, 0, &ioflags, oh->mesg[curmesg].raw);
-
- /* Save 'native' form of ref. count message */
- oh->mesg[curmesg].native = refcount;
-
- /* Set object header values */
- oh->has_refcount_msg = TRUE;
- oh->nlink = *refcount;
-
- /* Mark the object header as dirty if the message was changed by decoding */
- if((ioflags & H5O_DECODEIO_DIRTY) && (H5F_get_intent(f) & H5F_ACC_RDWR)) {
- oh->mesg[curmesg].dirty = TRUE;
- oh->cache_info.is_dirty = TRUE;
- }
- } /* end if */
- /* Check if next message to examine is a link message */
- else if(H5O_LINK_ID == oh->mesg[curmesg].type->id) {
- /* Increment the count of link messages */
- oh->link_msgs_seen++;
- } /* end if */
- /* Check if next message to examine is an attribute message */
- else if(H5O_ATTR_ID == oh->mesg[curmesg].type->id) {
- /* Increment the count of attribute messages */
- oh->attr_msgs_seen++;
- } /* end if */
- } /* end for */
- } /* end while */
-
- /* Mark the object header dirty if we've merged a message */
- if(merged_null_msgs)
- oh->cache_info.is_dirty = TRUE;
+ /* Read rest of the raw data */
+ if(H5F_block_read(f, H5FD_MEM_OHDR, (addr + spec_read_size), (buf_size - spec_read_size), dxpl_id, (buf + spec_read_size)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data")
+ } /* end if */
+ else
+ buf = read_buf;
-/* Don't check for the incorrect # of object header messages bug unless we've
- * enabled strict format checking. This allows for older files, created with
- * a version of the library that had a bug in tracking the correct # of header
- * messages to be read in without the library fussing about things. -QAK
- */
-#ifdef H5_STRICT_FORMAT_CHECKS
- /* Sanity check for the correct # of messages in object header */
- if(oh->version == H5O_VERSION_1)
- if((oh->nmesgs + merged_null_msgs) != nmesgs)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - too few messages")
-#else /* H5_STRICT_FORMAT_CHECKS */
- /* Check for incorrect # of messages in object header and if we have write
- * access on the file, flag the object header as dirty, so it gets fixed.
- */
- if(oh->version == H5O_VERSION_1)
- if((oh->nmesgs + merged_null_msgs) != nmesgs &&
- (H5F_get_intent(f) & H5F_ACC_RDWR))
- oh->cache_info.is_dirty = TRUE;
-#endif /* H5_STRICT_FORMAT_CHECKS */
+ /* Parse the first chunk */
+ if(H5O_chunk_deserialize(oh, addr, oh->chunk0_size, buf, &(udata->common), &oh->cache_info.is_dirty) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize first object header chunk")
-#ifdef H5O_DEBUG
-H5O_assert(oh);
-#endif /* H5O_DEBUG */
+ /* Note that we've loaded the object header from the file */
+ udata->made_attempt = TRUE;
/* Set return value */
ret_value = oh;
done:
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
+
/* Release the [possibly partially initialized] object header on errors */
if(!ret_value && oh)
if(H5O_free(oh) < 0)
@@ -664,7 +388,6 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t UNUSED addr, H5O_t *
/* flush */
if(oh->cache_info.is_dirty) {
uint8_t *p; /* Pointer to object header prefix buffer */
- unsigned u; /* Local index variable */
#ifdef H5O_DEBUG
H5O_assert(oh);
@@ -678,7 +401,10 @@ H5O_assert(oh);
* on the entire block of memory needs to be updated if anything is
* modified */
if(oh->version > H5O_VERSION_1) {
- uint64_t chunk0_size = oh->chunk[0].size - H5O_SIZEOF_HDR(oh); /* Size of chunk 0's data */
+ uint64_t chunk0_size; /* Size of chunk 0's data */
+
+ HDassert(oh->chunk[0].size >= (size_t)H5O_SIZEOF_HDR(oh));
+ chunk0_size = oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh);
/* Verify magic number */
HDassert(!HDmemcmp(p, H5O_HDR_MAGIC, H5_SIZEOF_MAGIC));
@@ -749,7 +475,7 @@ H5O_assert(oh);
UINT32ENCODE(p, oh->nlink);
/* First chunk size */
- UINT32ENCODE(p, (oh->chunk[0].size - H5O_SIZEOF_HDR(oh)));
+ UINT32ENCODE(p, (oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh)));
/* Zero to alignment */
HDmemset(p, 0, (size_t)(H5O_SIZEOF_HDR(oh) - 12));
@@ -757,57 +483,14 @@ H5O_assert(oh);
} /* end else */
HDassert((size_t)(p - oh->chunk[0].image) == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
- /* Mark chunk 0 as dirty, since the object header prefix has been updated */
- /* (this could be more sophisticated and track whether any prefix fields
- * have been changed, which could save I/O accesses if the
- * messages in chunk 0 haven't changed - QAK)
- */
- HDassert(H5F_addr_eq(addr, oh->chunk[0].addr));
- oh->chunk[0].dirty = TRUE;
-
- /* Encode any dirty messages */
- if(H5O_flush_msgs(f, oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object header messages")
-
- /* Write each chunk to disk, if it's dirty */
- for(u = 0; u < oh->nchunks; u++) {
- /* Sanity checks */
- if(oh->version > H5O_VERSION_1)
- /* Make certain the magic # is present */
- HDassert(!HDmemcmp(oh->chunk[u].image, (u == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5_SIZEOF_MAGIC));
- else
- /* Gaps should never occur in version 1 of the format */
- HDassert(oh->chunk[u].gap == 0);
-
- /* Write out chunk, if it's dirty */
- if(oh->chunk[u].dirty) {
- /* Extra work, for later versions of the format */
- if(oh->version > H5O_VERSION_1) {
- uint32_t metadata_chksum; /* Computed metadata checksum value */
-
- /* Check for gap in chunk & zero it out */
- if(oh->chunk[u].gap)
- HDmemset((oh->chunk[u].image + oh->chunk[u].size) -
- (H5O_SIZEOF_CHKSUM + oh->chunk[u].gap), 0, oh->chunk[u].gap);
-
- /* Compute metadata checksum */
- metadata_chksum = H5_checksum_metadata(oh->chunk[u].image, (oh->chunk[u].size - H5O_SIZEOF_CHKSUM), 0);
-
- /* Metadata checksum */
- p = oh->chunk[u].image + (oh->chunk[u].size - H5O_SIZEOF_CHKSUM);
- UINT32ENCODE(p, metadata_chksum);
- } /* end if */
+ /* Serialize messages for this chunk */
+ if(H5O_chunk_serialize(f, oh, (unsigned)0) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize first object header chunk")
- /* Write the chunk out */
- HDassert(H5F_addr_defined(oh->chunk[u].addr));
- if(H5F_block_write(f, H5FD_MEM_OHDR, oh->chunk[u].addr,
- oh->chunk[u].size, dxpl_id, oh->chunk[u].image) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header chunk to disk")
-
- /* Mark chunk as clean now */
- oh->chunk[u].dirty = FALSE;
- } /* end if */
- } /* end for */
+ /* Write the chunk out */
+ HDassert(H5F_addr_defined(oh->chunk[0].addr));
+ if(H5F_block_write(f, H5FD_MEM_OHDR, oh->chunk[0].addr, oh->chunk[0].size, dxpl_id, oh->chunk[0].image) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header chunk to disk")
/* Mark object header as clean now */
oh->cache_info.is_dirty = FALSE;
@@ -845,6 +528,7 @@ H5O_dest(H5F_t *f, H5O_t *oh)
/* check args */
HDassert(oh);
+ HDassert(oh->rc == 0);
/* Verify that node is clean */
HDassert(!oh->cache_info.is_dirty);
@@ -893,17 +577,13 @@ H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy)
/* check args */
HDassert(oh);
- /* Mark chunks as clean */
- for(u = 0; u < oh->nchunks; u++)
- oh->chunk[u].dirty = FALSE;
-
/* Mark messages as clean */
for(u = 0; u < oh->nmesgs; u++)
oh->mesg[u].dirty = FALSE;
#ifndef NDEBUG
- /* Reset the number of messages dirtied by decoding */
- oh->ndecode_dirtied = 0;
+ /* Reset the number of messages dirtied by decoding */
+ oh->ndecode_dirtied = 0;
#endif /* NDEBUG */
/* Mark whole header as clean */
@@ -935,22 +615,767 @@ done:
static herr_t
H5O_size(const H5F_t UNUSED *f, const H5O_t *oh, size_t *size_ptr)
{
- size_t size; /* Running sum of the object header's size */
- unsigned u; /* Local index variable */
-
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_size)
/* check args */
HDassert(oh);
HDassert(size_ptr);
- /* Add sizes of all the chunks */
- /* (includes size of prefix, in chunk 0) */
- for(u = 0, size = 0; u < oh->nchunks; u++)
- size += oh->chunk[u].size;
-
- *size_ptr = size;
+ /* Report the object header's prefix+first chunk length */
+ *size_ptr = (size_t)H5O_SIZEOF_HDR(oh) + oh->chunk0_size;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5O_size() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_cache_chk_load
+ *
+ * Purpose: Loads an object header continuation chunk from disk.
+ *
+ * Return: Success: Pointer to the new object header chunk proxy.
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5O_chunk_proxy_t *
+H5O_cache_chk_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
+ void *_udata2)
+{
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk proxy object */
+ H5O_chk_cache_ud_t *udata = (H5O_chk_cache_ud_t *)_udata2; /* User data for callback */
+ H5WB_t *wb = NULL; /* Wrapped buffer for prefix data */
+ uint8_t chunk_buf[H5O_SPEC_READ_SIZE]; /* Buffer for speculative read */
+ uint8_t *buf; /* Buffer to decode */
+ H5O_chunk_proxy_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_cache_chk_load)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(udata);
+ HDassert(udata->oh);
+
+ /* Allocate space for the object header data structure */
+ if(NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed")
+
+ /* Wrap the local buffer for serialized header info */
+ if(NULL == (wb = H5WB_wrap(chunk_buf, sizeof(chunk_buf))))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't wrap buffer")
+
+ /* Get a pointer to a buffer that's large enough for serialized header */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, udata->chunk_size)))
+ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't get actual buffer")
+
+ /* Read rest of the raw data */
+ if(H5F_block_read(f, H5FD_MEM_OHDR, addr, udata->chunk_size, dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header continuation chunk")
+
+ /* Check if we are still decoding the object header */
+ /* (as opposed to bringing a piece of it back from the file) */
+ if(udata->decoding) {
+ /* Sanity check */
+ HDassert(udata->common.f);
+ HDassert(udata->common.cont_msg_info);
+
+ /* Parse the chunk */
+ if(H5O_chunk_deserialize(udata->oh, addr, udata->chunk_size, buf, &(udata->common), &chk_proxy->cache_info.is_dirty) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize object header chunk")
+
+ /* Set the fields for the chunk proxy */
+ chk_proxy->oh = udata->oh;
+ chk_proxy->chunkno = udata->oh->nchunks - 1;
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(udata->chunkno < udata->oh->nchunks);
+
+ /* Set the fields for the chunk proxy */
+ chk_proxy->oh = udata->oh;
+ chk_proxy->chunkno = udata->chunkno;
+
+ /* Sanity check that the chunk representation we have in memory is the same
+ * as the one being brought in from disk.
+ */
+ HDassert(0 == HDmemcmp(buf, chk_proxy->oh->chunk[chk_proxy->chunkno].image, chk_proxy->oh->chunk[chk_proxy->chunkno].size));
+ } /* end else */
+
+ /* Increment reference count of object header */
+ if(H5O_inc_rc(udata->oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "can't increment reference count on object header")
+
+ /* Set return value */
+ ret_value = chk_proxy;
+
+done:
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
+
+ /* Release the [possibly partially initialized] object header on errors */
+ if(!ret_value && chk_proxy)
+ if(H5O_chunk_proxy_dest(chk_proxy) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header chunk proxy")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_cache_chk_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_cache_chk_flush
+ *
+ * Purpose: Flushes (and destroys) an object header continuation chunk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 12 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_cache_chk_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
+ H5O_chunk_proxy_t *chk_proxy, unsigned UNUSED * flags_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_cache_chk_flush)
+
+ /* flush */
+ if(chk_proxy->cache_info.is_dirty) {
+ /* Serialize messages for this chunk */
+ if(H5O_chunk_serialize(f, chk_proxy->oh, chk_proxy->chunkno) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header continuation chunk")
+
+ /* Write the chunk out */
+ HDassert(H5F_addr_defined(chk_proxy->oh->chunk[chk_proxy->chunkno].addr));
+ HDassert(H5F_addr_eq(addr, chk_proxy->oh->chunk[chk_proxy->chunkno].addr));
+ if(H5F_block_write(f, H5FD_MEM_OHDR, addr, chk_proxy->oh->chunk[chk_proxy->chunkno].size, dxpl_id, chk_proxy->oh->chunk[chk_proxy->chunkno].image) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header continuation chunk to disk")
+
+ /* Mark object header as clean now */
+ chk_proxy->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ /* Destroy the object header, if requested */
+ if(destroy)
+ if(H5O_cache_chk_dest(f, chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header continuation chunk data")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_cache_chk_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_cache_chk_dest
+ *
+ * Purpose: Destroys an object header continuation chunk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 12, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_cache_chk_dest(H5F_t *f, H5O_chunk_proxy_t *chk_proxy)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_cache_chk_dest)
+
+ /* Check arguments */
+ HDassert(chk_proxy);
+ HDassert(chk_proxy->chunkno > 0);
+
+ /* Verify that node is clean */
+ HDassert(chk_proxy->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!chk_proxy->cache_info.free_file_space_on_destroy || H5F_addr_defined(chk_proxy->cache_info.addr));
+
+ /* Check for releasing file space for object header */
+ if(chk_proxy->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_dxpl_id, chk_proxy->oh->chunk[chk_proxy->chunkno].addr, (hsize_t)chk_proxy->oh->chunk[chk_proxy->chunkno].size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header continuation chunk")
+ } /* end if */
+
+ /* Destroy object header chunk proxy */
+ if(H5O_chunk_proxy_dest(chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk proxy")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_cache_chk_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_cache_chk_clear
+ *
+ * Purpose: Mark a object header continuation chunk in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 12, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_cache_chk_clear(H5F_t *f, H5O_chunk_proxy_t *chk_proxy, hbool_t destroy)
+{
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_cache_chk_clear)
+
+ /* check args */
+ HDassert(chk_proxy);
+
+ /* Mark messages in chunk as clean */
+ for(u = 0; u < chk_proxy->oh->nmesgs; u++)
+ if(chk_proxy->oh->mesg[u].chunkno == chk_proxy->chunkno)
+ chk_proxy->oh->mesg[u].dirty = FALSE;
+
+ /* Mark as clean */
+ chk_proxy->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5O_cache_chk_dest(f, chk_proxy) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header continuation chunk data")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_cache_chk_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_cache_chk_size
+ *
+ * Purpose: Compute the size in bytes of the specified instance of
+ * an object header continuation chunk on disk, and return it in
+ * *len_ptr. On failure, the value of *len_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 12, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_cache_chk_size(const H5F_t UNUSED *f, const H5O_chunk_proxy_t *chk_proxy, size_t *size_ptr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_cache_chk_size)
+
+ /* check args */
+ HDassert(chk_proxy);
+ HDassert(size_ptr);
+
+ /* Report the object header continuation chunk's length */
+ *size_ptr = chk_proxy->oh->chunk[chk_proxy->chunkno].size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5O_cache_chk_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_add_cont_msg
+ *
+ * Purpose: Add information from a continuation message to the list of
+ * continuation messages in the object header
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 12, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_add_cont_msg(H5O_cont_msgs_t *cont_msg_info, const H5O_cont_t *cont)
+{
+ unsigned contno; /* Continuation message index */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_add_cont_msg)
+
+ /* Check arguments */
+ HDassert(cont_msg_info);
+ HDassert(cont);
+
+ /* Increase chunk array size, if necessary */
+ if(cont_msg_info->nmsgs >= cont_msg_info->alloc_nmsgs) {
+ unsigned na = MAX(H5O_NCHUNKS, cont_msg_info->alloc_nmsgs * 2); /* Double # of messages allocated */
+ H5O_cont_t *x = H5FL_SEQ_REALLOC(H5O_cont_t, cont_msg_info->msgs, (size_t)na);
+
+ if(!x)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "memory allocation failed")
+ cont_msg_info->alloc_nmsgs = na;
+ cont_msg_info->msgs = x;
+ } /* end if */
+
+ /* Init the continuation message info */
+ contno = cont_msg_info->nmsgs++;
+ cont_msg_info->msgs[contno].addr = cont->addr;
+ cont_msg_info->msgs[contno].size = cont->size;
+ cont_msg_info->msgs[contno].chunkno = cont->chunkno;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_add_cont_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_chunk_deserialize
+ *
+ * Purpose: Deserialize a chunk for an object header
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 12, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image,
+ H5O_common_cache_ud_t *udata, hbool_t *dirty)
+{
+ const uint8_t *p; /* Pointer into buffer to decode */
+ uint8_t *eom_ptr; /* Pointer to end of messages for a chunk */
+ unsigned curmesg; /* Current message being decoded in object header */
+ unsigned merged_null_msgs = 0; /* Number of null messages merged together */
+ unsigned chunkno; /* Current chunk's index */
+#ifndef NDEBUG
+ unsigned nullcnt; /* Count of null messages (for sanity checking gaps in chunks) */
+#endif /* NDEBUG */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_chunk_deserialize)
+
+ /* Check arguments */
+ HDassert(oh);
+ HDassert(image);
+ HDassert(udata->f);
+ HDassert(udata->cont_msg_info);
+
+ /* Increase chunk array size, if necessary */
+ if(oh->nchunks >= oh->alloc_nchunks) {
+ unsigned na = MAX(H5O_NCHUNKS, oh->alloc_nchunks * 2); /* Double # of chunks allocated */
+ H5O_chunk_t *x = H5FL_SEQ_REALLOC(H5O_chunk_t, oh->chunk, (size_t)na);
+
+ if(!x)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed")
+ oh->alloc_nchunks = na;
+ oh->chunk = x;
+ } /* end if */
+
+ /* Init the chunk data info */
+ chunkno = oh->nchunks++;
+ oh->chunk[chunkno].gap = 0;
+ if(chunkno == 0) {
+ /* First chunk's 'image' includes room for the object header prefix */
+ oh->chunk[0].addr = addr;
+ oh->chunk[0].size = len + (size_t)H5O_SIZEOF_HDR(oh);
+ } /* end if */
+ else {
+ oh->chunk[chunkno].addr = addr;
+ oh->chunk[chunkno].size = len;
+ } /* end else */
+ if(NULL == (oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, oh->chunk[chunkno].size)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed")
+
+ /* Copy disk image into chunk's image */
+ HDmemcpy(oh->chunk[chunkno].image, image, oh->chunk[chunkno].size);
+
+ /* Point into chunk image to decode */
+ p = oh->chunk[chunkno].image;
+
+ /* Handle chunk 0 as special case */
+ if(chunkno == 0)
+ /* Skip over [already decoded] prefix */
+ p += (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh));
+ /* Check for magic # on chunks > 0 in later versions of the format */
+ else if(chunkno > 0 && oh->version > H5O_VERSION_1) {
+ /* Magic number */
+ if(HDmemcmp(p, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "wrong object header chunk signature")
+ p += H5_SIZEOF_MAGIC;
+ } /* end if */
+
+ /* Save # of messages already inspected */
+ curmesg = oh->nmesgs;
+
+ /* Decode messages from this chunk */
+ eom_ptr = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh));
+#ifndef NDEBUG
+ nullcnt = 0;
+#endif /* NDEBUG */
+ while(p < eom_ptr) {
+ unsigned mesgno; /* Current message to operate on */
+ size_t mesg_size; /* Size of message read in */
+ unsigned id; /* ID (type) of current message */
+ uint8_t flags; /* Flags for current message */
+ H5O_msg_crt_idx_t crt_idx = 0; /* Creation index for current message */
+
+ /* Decode message prefix info */
+
+ /* Version # */
+ if(oh->version == H5O_VERSION_1)
+ UINT16DECODE(p, id)
+ else
+ id = *p++;
+
+ /* Check for unknown message ID getting encoded in file */
+ if(id == H5O_UNKNOWN_ID)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "'unknown' message ID encoded in file?!?")
+
+ /* Message size */
+ UINT16DECODE(p, mesg_size);
+ HDassert(mesg_size == H5O_ALIGN_OH(oh, mesg_size));
+
+ /* Message flags */
+ flags = *p++;
+ if(flags & ~H5O_MSG_FLAG_BITS)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unknown flag for message")
+ if((flags & H5O_MSG_FLAG_SHARED) && (flags & H5O_MSG_FLAG_DONTSHARE))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "bad flag combination for message")
+ if((flags & H5O_MSG_FLAG_WAS_UNKNOWN) && (flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "bad flag combination for message")
+ if((flags & H5O_MSG_FLAG_WAS_UNKNOWN) && !(flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "bad flag combination for message")
+
+ /* Reserved bytes/creation index */
+ if(oh->version == H5O_VERSION_1)
+ p += 3; /*reserved*/
+ else {
+ /* Only decode creation index if they are being tracked */
+ if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)
+ UINT16DECODE(p, crt_idx);
+ } /* end else */
+
+ /* Try to detect invalidly formatted object header message that
+ * extends past end of chunk.
+ */
+ if(p + mesg_size > eom_ptr)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "corrupt object header")
+
+#ifndef NDEBUG
+ /* Increment count of null messages */
+ if(H5O_NULL_ID == id)
+ nullcnt++;
+#endif /* NDEBUG */
+
+ /* Check for combining two adjacent 'null' messages */
+ if((udata->file_intent & H5F_ACC_RDWR) &&
+ H5O_NULL_ID == id && oh->nmesgs > 0 &&
+ H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id &&
+ oh->mesg[oh->nmesgs - 1].chunkno == chunkno) {
+
+ /* Combine adjacent null messages */
+ mesgno = oh->nmesgs - 1;
+ oh->mesg[mesgno].raw_size += H5O_SIZEOF_MSGHDR_OH(oh) + mesg_size;
+ oh->mesg[mesgno].dirty = TRUE;
+ merged_null_msgs++;
+ udata->merged_null_msgs++;
+ } /* end if */
+ else {
+ /* Check if we need to extend message table to hold the new message */
+ if(oh->nmesgs >= oh->alloc_nmesgs)
+ if(H5O_alloc_msgs(oh, (size_t)1) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "can't allocate more space for messages")
+
+ /* Get index for message */
+ mesgno = oh->nmesgs++;
+
+ /* Initialize information about message */
+ oh->mesg[mesgno].dirty = FALSE;
+ oh->mesg[mesgno].flags = flags;
+ oh->mesg[mesgno].crt_idx = crt_idx;
+ oh->mesg[mesgno].native = NULL;
+ oh->mesg[mesgno].raw = (uint8_t *)p; /* Casting away const OK - QAK */
+ oh->mesg[mesgno].raw_size = mesg_size;
+ oh->mesg[mesgno].chunkno = chunkno;
+
+ /* Point unknown messages at 'unknown' message class */
+ /* (Usually from future versions of the library) */
+ if(id >= NELMTS(H5O_msg_class_g) || NULL == H5O_msg_class_g[id]) {
+ H5O_unknown_t *unknown; /* Pointer to "unknown" message info */
+
+ /* Allocate "unknown" message info */
+ if(NULL == (unknown = H5FL_MALLOC(H5O_unknown_t)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed")
+
+ /* Save the original message type ID */
+ *unknown = id;
+
+ /* Save 'native' form of unknown message */
+ oh->mesg[mesgno].native = unknown;
+
+ /* Set message to "unknown" class */
+ oh->mesg[mesgno].type = H5O_msg_class_g[H5O_UNKNOWN_ID];
+
+ /* Check for "fail if unknown" message flag */
+ if(flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unknown message with 'fail if unknown' flag found")
+ /* Check for "mark if unknown" message flag, etc. */
+ else if((flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN) &&
+ !(flags & H5O_MSG_FLAG_WAS_UNKNOWN) &&
+ (udata->file_intent & H5F_ACC_RDWR)) {
+
+ /* Mark the message as "unknown" */
+ /* This is a bit aggressive, since the application may
+ * never change anything about the object (metadata or
+ * raw data), but we can sort out the finer details
+ * when/if we start using the flag - QAK
+ */
+ /* Also, it's possible that this functionality may not
+ * get invoked if the object header is brought into
+ * the metadata cache in some other "weird" way, like
+ * using H5Ocopy() - QAK
+ */
+ oh->mesg[mesgno].flags |= H5O_MSG_FLAG_WAS_UNKNOWN;
+
+ /* Mark the message and chunk as dirty */
+ oh->mesg[mesgno].dirty = TRUE;
+ udata->mesgs_modified = TRUE;
+ *dirty = TRUE;
+ } /* end if */
+ } /* end if */
+ else
+ /* Set message class for "known" messages */
+ oh->mesg[mesgno].type = H5O_msg_class_g[id];
+ } /* end else */
+
+ /* Advance decode pointer past message */
+ p += mesg_size;
+
+ /* Check for 'gap' at end of chunk */
+ if((eom_ptr - p) > 0 && (eom_ptr - p) < H5O_SIZEOF_MSGHDR_OH(oh)) {
+ /* Gaps can only occur in later versions of the format */
+ HDassert(oh->version > H5O_VERSION_1);
+
+ /* Gaps should only occur in chunks with no null messages */
+ HDassert(nullcnt == 0);
+
+ /* Set gap information for chunk */
+ oh->chunk[chunkno].gap = (size_t)(eom_ptr - p);
+
+ /* Increment location in chunk */
+ p += oh->chunk[chunkno].gap;
+ } /* end if */
+ } /* end while */
+
+ /* Check for correct checksum on chunks, in later versions of the format */
+ if(oh->version > H5O_VERSION_1) {
+ uint32_t stored_chksum; /* Checksum from file */
+ uint32_t computed_chksum; /* Checksum computed in memory */
+
+ /* Metadata checksum */
+ UINT32DECODE(p, stored_chksum);
+
+ /* Compute checksum on chunk */
+ computed_chksum = H5_checksum_metadata(oh->chunk[chunkno].image, (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM), 0);
+
+ /* Verify checksum */
+ if(stored_chksum != computed_chksum)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "incorrect metadata checksum for object header chunk")
+ } /* end if */
+
+ /* Sanity check */
+ HDassert(p == oh->chunk[chunkno].image + oh->chunk[chunkno].size);
+
+ /* Do some inspection/interpretation of new messages from this chunk */
+ /* (detect continuation messages, ref. count messages, etc.) */
+ while(curmesg < oh->nmesgs) {
+ /* Check if next message to examine is a continuation message */
+ if(H5O_CONT_ID == oh->mesg[curmesg].type->id) {
+ H5O_cont_t *cont;
+ unsigned ioflags = 0; /* Flags for decode routine */
+
+ /* Decode continuation message */
+ cont = (H5O_cont_t *)(H5O_MSG_CONT->decode)(udata->f, udata->dxpl_id, NULL, 0, &ioflags, oh->mesg[curmesg].raw);
+ cont->chunkno = udata->cont_msg_info->nmsgs + 1; /*the next continuation message/chunk */
+
+ /* Save 'native' form of continuation message */
+ oh->mesg[curmesg].native = cont;
+
+ /* Add to continuation messages left to interpret */
+ if(H5O_add_cont_msg(udata->cont_msg_info, cont) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't add continuation message")
+
+ /* Mark the message & chunk as dirty if the message was changed by decoding */
+ if((ioflags & H5O_DECODEIO_DIRTY) && (udata->file_intent & H5F_ACC_RDWR)) {
+ oh->mesg[curmesg].dirty = TRUE;
+ udata->mesgs_modified = TRUE;
+ *dirty = TRUE;
+ } /* end if */
+ } /* end if */
+ /* Check if next message to examine is a ref. count message */
+ else if(H5O_REFCOUNT_ID == oh->mesg[curmesg].type->id) {
+ H5O_refcount_t *refcount;
+ unsigned ioflags = 0; /* Flags for decode routine */
+
+ /* Decode ref. count message */
+ HDassert(oh->version > H5O_VERSION_1);
+ refcount = (H5O_refcount_t *)(H5O_MSG_REFCOUNT->decode)(udata->f, udata->dxpl_id, NULL, 0, &ioflags, oh->mesg[curmesg].raw);
+
+ /* Save 'native' form of ref. count message */
+ oh->mesg[curmesg].native = refcount;
+
+ /* Set object header values */
+ oh->has_refcount_msg = TRUE;
+ oh->nlink = *refcount;
+
+ /* Mark the message & chunk as dirty if the message was changed by decoding */
+ if((ioflags & H5O_DECODEIO_DIRTY) && (udata->file_intent & H5F_ACC_RDWR)) {
+ oh->mesg[curmesg].dirty = TRUE;
+ udata->mesgs_modified = TRUE;
+ *dirty = TRUE;
+ } /* end if */
+ } /* end if */
+ /* Check if next message to examine is a link message */
+ else if(H5O_LINK_ID == oh->mesg[curmesg].type->id) {
+ /* Increment the count of link messages */
+ oh->link_msgs_seen++;
+ } /* end if */
+ /* Check if next message to examine is an attribute message */
+ else if(H5O_ATTR_ID == oh->mesg[curmesg].type->id) {
+ /* Increment the count of attribute messages */
+ oh->attr_msgs_seen++;
+ } /* end if */
+
+ /* Advance to next message */
+ curmesg++;
+ } /* end while */
+
+ /* Mark the chunk dirty if we've merged null messages */
+ if(merged_null_msgs) {
+ udata->mesgs_modified = TRUE;
+ *dirty = TRUE;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_chunk_deserialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_chunk_serialize
+ *
+ * Purpose: Serialize a chunk for an object header
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 12, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno)
+{
+ H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_chunk_serialize)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(oh);
+
+ /* Encode any dirty messages in this chunk */
+ for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++)
+ if(curr_msg->dirty && curr_msg->chunkno == chunkno)
+ /* Casting away const OK -QAK */
+ if(H5O_msg_flush((H5F_t *)f, oh, curr_msg) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message")
+
+ /* Sanity checks */
+ if(oh->version > H5O_VERSION_1)
+ /* Make certain the magic # is present */
+ HDassert(!HDmemcmp(oh->chunk[chunkno].image, (chunkno == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5_SIZEOF_MAGIC));
+ else
+ /* Gaps should never occur in version 1 of the format */
+ HDassert(oh->chunk[chunkno].gap == 0);
+
+ /* Extra work, for later versions of the format */
+ if(oh->version > H5O_VERSION_1) {
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ uint8_t *p; /* Pointer into object header chunk */
+
+ /* Check for gap in chunk & zero it out */
+ if(oh->chunk[chunkno].gap)
+ HDmemset((oh->chunk[chunkno].image + oh->chunk[chunkno].size) -
+ (H5O_SIZEOF_CHKSUM + oh->chunk[chunkno].gap), 0, oh->chunk[chunkno].gap);
+
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(oh->chunk[chunkno].image, (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM), 0);
+
+ /* Metadata checksum */
+ p = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM);
+ UINT32ENCODE(p, metadata_chksum);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_chunk_serialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_chunk_proxy_dest
+ *
+ * Purpose: Destroy a chunk proxy object
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * July 13, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_chunk_proxy_dest(H5O_chunk_proxy_t *chk_proxy)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_chunk_proxy_dest)
+
+ /* Check arguments */
+ HDassert(chk_proxy);
+
+ /* Decrement reference count of object header */
+ if(H5O_dec_rc(chk_proxy->oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "can't decrement reference count on object header")
+
+ /* Release the chunk proxy object */
+ chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_chunk_proxy_dest() */
+
diff --git a/src/H5Ochunk.c b/src/H5Ochunk.c
new file mode 100644
index 0000000..59102b6
--- /dev/null
+++ b/src/H5Ochunk.c
@@ -0,0 +1,359 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Ochunk.c
+ * Jul 13 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Object header chunk routines.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5O_PACKAGE /*suppress error about including H5Opkg */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Opkg.h" /* Object headers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Declare the free list for H5O_chunk_proxy_t's */
+H5FL_DEFINE(H5O_chunk_proxy_t);
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_chunk_add
+ *
+ * Purpose: Add new chunk for object header to metadata cache
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_chunk_add(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
+{
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Proxy for chunk, to mark it dirty in the cache */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_chunk_add, FAIL)
+
+ /* check args */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(idx < oh->nchunks);
+ HDassert(idx > 0);
+
+ /* Allocate space for the object header data structure */
+ if(NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Set the values in the chunk proxy */
+ chk_proxy->oh = oh;
+ chk_proxy->chunkno = idx;
+
+ /* Insert the chunk proxy into the cache */
+ if(H5AC_set(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, chk_proxy, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header chunk")
+ chk_proxy = NULL;
+
+ /* Increment reference count on object header */
+ if(H5O_inc_rc(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, FAIL, "can't increment reference count on object header")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_chunk_add() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_chunk_protect
+ *
+ * Purpose: Protect an object header chunk for modifications
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 17 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+H5O_chunk_proxy_t *
+H5O_chunk_protect(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
+{
+ H5O_chunk_proxy_t *chk_proxy; /* Proxy for protected chunk */
+ H5O_chunk_proxy_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_chunk_protect, NULL)
+
+ /* check args */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(idx < oh->nchunks);
+
+ /* Check for protecting first chunk */
+ if(0 == idx) {
+ /* Create new "fake" chunk proxy for first chunk */
+ /* (since the first chunk is already handled by the H5O_t object) */
+ if(NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed")
+
+ /* Set chunk proxy fields */
+ chk_proxy->oh = oh;
+ chk_proxy->chunkno = idx;
+ } /* end if */
+ else {
+ H5O_chk_cache_ud_t chk_udata; /* User data for loading chunk */
+
+ /* Construct the user data for protecting chunk proxy */
+ /* (and _not_ decoding it) */
+ HDmemset(&chk_udata, 0, sizeof(chk_udata));
+ chk_udata.oh = oh;
+ chk_udata.chunkno = idx;
+ chk_udata.chunk_size = oh->chunk[idx].size;
+
+ /* Get the chunk proxy */
+ if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, NULL, &chk_udata, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header chunk")
+
+ /* Sanity check */
+ HDassert(chk_proxy->oh == oh);
+ HDassert(chk_proxy->chunkno == idx);
+ } /* end else */
+
+ /* Set return value */
+ ret_value = chk_proxy;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_chunk_protect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_chunk_unprotect
+ *
+ * Purpose: Unprotect an object header chunk after modifications
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 17 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_chunk_unprotect(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_chunk_proxy_t *chk_proxy,
+ unsigned chk_flags)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_chunk_unprotect, FAIL)
+
+ /* check args */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(chk_proxy);
+ HDassert(!(chk_flags & (unsigned)~(H5AC__DIRTIED_FLAG | H5AC__SIZE_CHANGED_FLAG)));
+
+ /* Check for releasing first chunk */
+ if(0 == chk_proxy->chunkno) {
+ /* Check for resizing the first chunk */
+ if(chk_flags & H5AC__SIZE_CHANGED_FLAG) {
+ /* Resize object header in cache */
+ if(H5AC_resize_pinned_entry(oh, oh->chunk[0].size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTRESIZE, FAIL, "unable to resize chunk in cache")
+ } /* end if */
+ /* Check for dirtying the first chunk */
+ else if(chk_flags & H5AC__DIRTIED_FLAG) {
+ /* Mark object header as dirty in cache */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
+ } /* end else/if */
+ else {
+ /* Sanity check */
+ HDassert(0 && "Unknown chunk proxy flag(s)?!?");
+ } /* end else */
+
+ /* Free fake chunk proxy */
+ chk_proxy = H5FL_FREE(H5O_chunk_proxy_t, chk_proxy);
+ } /* end if */
+ else {
+ /* Release the chunk proxy from the cache, marking it dirty */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[chk_proxy->chunkno].addr, chk_proxy, chk_flags) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_chunk_unprotect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_chunk_update_idx
+ *
+ * Purpose: Update the chunk index for a chunk proxy
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_chunk_update_idx(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
+{
+ H5O_chunk_proxy_t *chk_proxy; /* Proxy for chunk, to mark it dirty in the cache */
+ H5O_chk_cache_ud_t chk_udata; /* User data for loading chunk */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_chunk_update_idx, FAIL)
+
+ /* check args */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(idx < oh->nchunks);
+ HDassert(idx > 0);
+
+ /* Construct the user data for protecting chunk proxy */
+ /* (and _not_ decoding it) */
+ HDmemset(&chk_udata, 0, sizeof(chk_udata));
+ chk_udata.oh = oh;
+ chk_udata.chunkno = idx;
+ chk_udata.chunk_size = oh->chunk[idx].size;
+
+ /* Get the chunk proxy */
+ if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, NULL, &chk_udata, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
+ /* Update index for chunk proxy in cache */
+ chk_proxy->chunkno = idx;
+
+ /* Release the chunk proxy from the cache, marking it deleted */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, chk_proxy, H5AC__DIRTIED_FLAG) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_chunk_update_idx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_chunk_delete
+ *
+ * Purpose: Notify metadata cache that a chunk has been deleted
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jul 13 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_chunk_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx)
+{
+ H5O_chunk_proxy_t *chk_proxy; /* Proxy for chunk, to mark it dirty in the cache */
+ H5O_chk_cache_ud_t chk_udata; /* User data for loading chunk */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_chunk_delete, FAIL)
+
+ /* check args */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(idx < oh->nchunks);
+ HDassert(idx > 0);
+
+ /* Construct the user data for protecting chunk proxy */
+ /* (and _not_ decoding it) */
+ HDmemset(&chk_udata, 0, sizeof(chk_udata));
+ chk_udata.oh = oh;
+ chk_udata.chunkno = idx;
+ chk_udata.chunk_size = oh->chunk[idx].size;
+
+ /* Get the chunk proxy */
+ if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, NULL, &chk_udata, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
+ /* Sanity check */
+ HDassert(chk_proxy->oh == oh);
+ HDassert(chk_proxy->chunkno == idx);
+
+ /* Release the chunk proxy from the cache, marking it deleted */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_OHDR_CHK, oh->chunk[idx].addr, chk_proxy, (H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header chunk")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_chunk_delete() */
+
diff --git a/src/H5Ocont.c b/src/H5Ocont.c
index df336dd..7f9dd47 100644
--- a/src/H5Ocont.c
+++ b/src/H5Ocont.c
@@ -224,7 +224,7 @@ H5O_cont_free(void *mesg)
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_cont_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *_mesg)
+H5O_cont_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg)
{
H5O_cont_t *mesg = (H5O_cont_t *) _mesg;
herr_t ret_value = SUCCEED; /* Return value */
@@ -235,9 +235,10 @@ H5O_cont_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *_mesg)
HDassert(f);
HDassert(mesg);
- /* Release space for chunk */
- if(H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, mesg->addr, (hsize_t)mesg->size) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header chunk")
+ /* Notify the cache that the chunk has been deleted */
+ /* (releases the space for the chunk) */
+ if(H5O_chunk_delete(f, dxpl_id, open_oh, mesg->chunkno) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to remove chunk from cache")
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c
index 8896795..163e525 100644
--- a/src/H5Ocopy.c
+++ b/src/H5Ocopy.c
@@ -316,7 +316,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
HDassert(cpy_info);
/* Get source object header */
- if(NULL == (oh_src = (H5O_t *)H5AC_protect(oloc_src->file, dxpl_id, H5AC_OHDR, oloc_src->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh_src = H5O_protect(oloc_src, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Get pointer to object class for this object */
@@ -579,7 +579,6 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Set dest. chunk information */
- oh_dst->chunk[0].dirty = TRUE;
oh_dst->chunk[0].size = (size_t)dst_oh_size;
oh_dst->chunk[0].gap = dst_oh_gap;
@@ -739,7 +738,7 @@ done:
HDfree(deleted);
/* Release pointer to source object header and its derived objects */
- if(oh_src && H5AC_unprotect(oloc_src->file, dxpl_id, H5AC_OHDR, oloc_src->addr, oh_src, H5AC__NO_FLAGS_SET) < 0)
+ if(oh_src && H5O_unprotect(oloc_src, dxpl_id, oh_src, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
/* Release pointer to destination object header */
diff --git a/src/H5Odbg.c b/src/H5Odbg.c
index 9285f4b..8661cfe 100644
--- a/src/H5Odbg.c
+++ b/src/H5Odbg.c
@@ -377,10 +377,6 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
HDfprintf(stream, "%*sChunk %d...\n", indent, "", i);
- HDfprintf(stream, "%*s%-*s %t\n", indent + 3, "", MAX(0, fwidth - 3),
- "Dirty:",
- oh->chunk[i].dirty);
-
HDfprintf(stream, "%*s%-*s %a\n", indent + 3, "", MAX(0, fwidth - 3),
"Address:",
oh->chunk[i].addr);
@@ -538,6 +534,7 @@ herr_t
H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth)
{
H5O_t *oh = NULL; /* Object header to display */
+ H5O_loc_t loc; /* Object location for object to delete */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5O_debug, FAIL)
@@ -549,14 +546,19 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f
HDassert(indent >= 0);
HDassert(fwidth >= 0);
- if(NULL == (oh = (H5O_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_READ)))
+ /* Set up the object location */
+ loc.file = f;
+ loc.addr = addr;
+ loc.holding_file = FALSE;
+
+ if(NULL == (oh = H5O_protect(&loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* debug */
H5O_debug_real(f, dxpl_id, oh, addr, stream, indent, fwidth);
done:
- if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ 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")
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index fc6146a..e2355ae 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -127,21 +127,17 @@ H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
HDassert(mesg);
- /* Check for write access on the file */
- if(0 == (H5F_INTENT(loc->file) & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file")
-
- /* Protect the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
+ /* Pin the object header */
+ if(NULL == (oh = H5O_pin(loc, dxpl_id)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
/* Go append message to object header */
if(H5O_msg_append_oh(loc->file, dxpl_id, oh, type_id, mesg_flags, update_flags, mesg) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to append to object header")
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_msg_create() */
@@ -280,21 +276,17 @@ H5O_msg_write(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
HDassert(mesg);
HDassert(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
- /* Check for write access on the file */
- if(0 == (H5F_INTENT(loc->file) & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file")
-
- /* Protect the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
+ /* Pin the object header */
+ if(NULL == (oh = H5O_pin(loc, dxpl_id)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
/* Call the "real" modify routine */
if(H5O_msg_write_real(loc->file, dxpl_id, oh, type, mesg_flags, update_flags, mesg) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message")
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_msg_write() */
@@ -484,7 +476,7 @@ H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, void *mesg,
HDassert(type_id < NELMTS(H5O_msg_class_g));
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header")
/* Call the "real" read routine */
@@ -492,7 +484,7 @@ H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, void *mesg,
HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to load object header")
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -809,14 +801,14 @@ H5O_msg_count(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
HDassert(type);
/* Load the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Count the messages of the correct type */
ret_value = H5O_msg_count_real(oh, type);
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ 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")
FUNC_LEAVE_NOAPI(ret_value)
@@ -890,7 +882,7 @@ H5O_msg_exists(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
HDassert(type_id < NELMTS(H5O_msg_class_g));
/* Load the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Call the "real" exists routine */
@@ -898,7 +890,7 @@ H5O_msg_exists(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
HGOTO_ERROR(H5E_OHDR, H5E_READERROR, FAIL, "unable to verify object header message")
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) != SUCCEED)
+ 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")
FUNC_LEAVE_NOAPI(ret_value)
@@ -986,17 +978,17 @@ H5O_msg_remove(const H5O_loc_t *loc, unsigned type_id, int sequence, hbool_t adj
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
HDassert(type);
- /* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
+ /* Pin the object header */
+ if(NULL == (oh = H5O_pin(loc, dxpl_id)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
/* Call the "real" remove routine */
if((ret_value = H5O_msg_remove_real(loc->file, oh, type, sequence, NULL, NULL, adj_link, dxpl_id)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to remove object header message")
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_msg_remove() */
@@ -1038,17 +1030,17 @@ H5O_msg_remove_op(const H5O_loc_t *loc, unsigned type_id, int sequence,
type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
HDassert(type);
- /* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
+ /* Pin the object header */
+ if(NULL == (oh = H5O_pin(loc, dxpl_id)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
/* Call the "real" remove routine */
if((ret_value = H5O_msg_remove_real(loc->file, oh, type, sequence, op, op_data, adj_link, dxpl_id)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to remove object header message")
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
+ if(oh && H5O_unpin(oh) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_msg_remove_op() */
@@ -1230,7 +1222,7 @@ H5O_msg_iterate(const H5O_loc_t *loc, unsigned type_id,
HDassert(op);
/* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Call the "real" iterate routine */
@@ -1238,7 +1230,7 @@ H5O_msg_iterate(const H5O_loc_t *loc, unsigned type_id,
HERROR(H5E_OHDR, H5E_BADITER, "unable to iterate over object header messages");
done:
- if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ 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")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1962,7 +1954,9 @@ H5O_copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx,
const H5O_msg_class_t *type, const void *mesg, unsigned mesg_flags,
unsigned update_flags)
{
+ H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */
H5O_mesg_t *idx_msg = &oh->mesg[idx]; /* Pointer to message to modify */
+ unsigned chk_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting chunk */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_copy_mesg)
@@ -1974,6 +1968,10 @@ H5O_copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx,
HDassert(type->copy);
HDassert(mesg);
+ /* Protect chunk */
+ if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, idx_msg->chunkno)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
+
/* Reset existing native information for the header's message */
H5O_msg_reset_real(type, idx_msg->native);
@@ -1986,17 +1984,23 @@ H5O_copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx,
/* Mark the message as modified */
idx_msg->dirty = TRUE;
+ chk_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Release chunk */
+ if(H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy, chk_flags) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+ chk_proxy = NULL;
/* Update the modification time, if requested */
if(update_flags & H5O_UPDATE_TIME)
if(H5O_touch_oh(f, dxpl_id, oh, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
- /* Mark object header as dirty in cache */
- if(H5AC_mark_pinned_or_protected_entry_dirty(oh) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
-
done:
+ /* Release chunk, if not already released */
+ if(chk_proxy && H5O_chunk_unprotect(f, dxpl_id, oh, chk_proxy, chk_flags) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_copy_mesg() */
@@ -2183,9 +2187,8 @@ H5O_msg_flush(H5F_t *f, H5O_t *oh, H5O_mesg_t *mesg)
HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message")
} /* end if */
- /* Pass "modifiedness" from message to chunk */
+ /* Mark the message as clean now */
mesg->dirty = FALSE;
- oh->chunk[mesg->chunkno].dirty = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index 3d0e627..4091944 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -253,7 +253,6 @@ struct H5O_mesg_t {
};
typedef struct H5O_chunk_t {
- hbool_t dirty; /*dirty flag */
haddr_t addr; /*chunk file address */
size_t size; /*chunk size */
size_t gap; /*space at end of chunk too small for null message */
@@ -268,9 +267,6 @@ struct H5O_t {
size_t sizeof_size; /* Size of file sizes */
size_t sizeof_addr; /* Size of file addresses */
- /* Misc. information (not stored) */
- unsigned npins; /* Number of times the header is pinned */
-
/* Debugging information (not stored) */
#ifdef H5O_ENABLE_BAD_MESG_COUNT
hbool_t store_bad_mesg_count; /* Flag to indicate that a bad message count should be stored */
@@ -282,6 +278,12 @@ struct H5O_t {
size_t ndecode_dirtied; /* Number of messages dirtied by decoding */
#endif /* NDEBUG */
+ /* Chunk management information (not stored) */
+ size_t rc; /* Reference count of [continuation] chunks using this structure */
+ size_t chunk0_size; /* Size of serialized first chunk */
+ hbool_t mesgs_modified; /* Whether any messages were modified when the object header was deserialized */
+ hbool_t prefix_modified; /* Whether prefix was modified when the object header was deserialized */
+
/* Object information (stored) */
hbool_t has_refcount_msg; /* Whether the object has a ref. count message */
unsigned nlink; /*link count */
@@ -332,10 +334,55 @@ typedef struct H5O_addr_map_t {
hsize_t inc_ref_count; /* Number of deferred increments to reference count */
} H5O_addr_map_t;
-
-/* H5O inherits cache-like properties from H5AC */
+/* Stack of continuation messages to interpret */
+typedef struct H5O_cont_msgs_t {
+ size_t nmsgs; /* Number of continuation messages found so far */
+ size_t alloc_nmsgs; /* Continuation messages allocated */
+ H5O_cont_t *msgs; /* Array of continuation messages */
+} H5O_cont_msgs_t;
+
+/* Common callback information for loading object header prefix from disk */
+typedef struct H5O_common_cache_ud_t {
+ H5F_t *f; /* Pointer to file for object header/chunk */
+ hid_t dxpl_id; /* DXPL for operation */
+ unsigned file_intent; /* Read/write intent for file */
+ unsigned merged_null_msgs; /* Number of null messages merged together */
+ hbool_t mesgs_modified; /* Whether any messages were modified when the object header was deserialized */
+ H5O_cont_msgs_t *cont_msg_info; /* Pointer to continuation messages to work on */
+} H5O_common_cache_ud_t;
+
+/* Callback information for loading object header prefix from disk */
+typedef struct H5O_cache_ud_t {
+ hbool_t made_attempt; /* Whether the deserialize routine was already attempted */
+ unsigned v1_pfx_nmesgs; /* Number of messages from v1 prefix header */
+ H5O_common_cache_ud_t common; /* Common object header cache callback info */
+} H5O_cache_ud_t;
+
+/* Structure representing each chunk in the cache */
+typedef struct H5O_chunk_proxy_t {
+ H5AC_info_t cache_info; /* Information for metadata cache functions, _must_ be */
+ /* first field in structure */
+
+ H5O_t *oh; /* Object header for this chunk */
+ unsigned chunkno; /* Chunk number for this chunk */
+} H5O_chunk_proxy_t;
+
+/* Callback information for loading object header chunk from disk */
+typedef struct H5O_chk_cache_ud_t {
+ hbool_t decoding; /* Whether the object header is being decoded */
+ H5O_t *oh; /* Object header for this chunk */
+ unsigned chunkno; /* Index of chunk being brought in (for re-loads) */
+ size_t chunk_size; /* Chunk size */
+ H5O_common_cache_ud_t common; /* Common object header cache callback info */
+} H5O_chk_cache_ud_t;
+
+
+/* H5O object header inherits cache-like properties from H5AC */
H5_DLLVAR const H5AC_class_t H5AC_OHDR[1];
+/* H5O object header chunk inherits cache-like properties from H5AC */
+H5_DLLVAR const H5AC_class_t H5AC_OHDR_CHK[1];
+
/* Header message ID to class mapping */
H5_DLLVAR const H5O_msg_class_t *const H5O_msg_class_g[H5O_MSG_TYPES];
@@ -476,6 +523,9 @@ H5_DLL herr_t H5O_flush_msgs(H5F_t *f, H5O_t *oh);
H5_DLL hid_t H5O_open_by_loc(const H5G_loc_t *obj_loc, hid_t lapl_id, hid_t dxpl_id, hbool_t app_ref);
H5_DLL herr_t H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_mesg_t *mesg);
H5_DLL const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh);
+H5_DLL int H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, hbool_t *deleted);
+H5_DLL herr_t H5O_inc_rc(H5O_t *oh);
+H5_DLL herr_t H5O_dec_rc(H5O_t *oh);
H5_DLL herr_t H5O_free(H5O_t *oh);
/* Object header message routines */
@@ -498,6 +548,15 @@ H5_DLL void *H5O_msg_copy_file(const H5O_msg_class_t *type, H5F_t *file_src,
H5_DLL herr_t H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
const H5O_mesg_operator_t *op, void *op_data, hid_t dxpl_id);
+/* Object header chunk routines */
+H5_DLL herr_t H5O_chunk_add(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx);
+H5_DLL H5O_chunk_proxy_t *H5O_chunk_protect(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
+ unsigned idx);
+H5_DLL herr_t H5O_chunk_unprotect(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
+ H5O_chunk_proxy_t *chk_proxy, unsigned chk_flags);
+H5_DLL herr_t H5O_chunk_update_idx(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx);
+H5_DLL herr_t H5O_chunk_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx);
+
/* Collect storage info for btree and heap */
H5_DLL herr_t H5O_attr_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
H5_ih_info_t *bh_info);
@@ -544,6 +603,7 @@ H5_DLL htri_t H5O_is_attr_dense_test(hid_t oid);
H5_DLL herr_t H5O_num_attrs_test(hid_t oid, hsize_t *nattrs);
H5_DLL herr_t H5O_attr_dense_info_test(hid_t oid, hsize_t *name_count, hsize_t *corder_count);
H5_DLL herr_t H5O_check_msg_marked_test(hid_t oid, hbool_t flag_val);
+H5_DLL herr_t H5O_expunge_chunks_test(const H5O_loc_t *oloc, hid_t dxpl_id);
#endif /* H5O_TESTING */
/* Object header debugging routines */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 39ae9cf..53c5426 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -37,6 +37,7 @@
#include "H5Spublic.h" /* Dataspace functions */
/* Private headers needed by this file */
+#include "H5ACprivate.h" /* Metadata cache */
#include "H5Fprivate.h" /* File access */
#include "H5SLprivate.h" /* Skip lists */
#include "H5Tprivate.h" /* Datatype functions */
@@ -623,9 +624,11 @@ H5_DLL herr_t H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint,
H5_DLL herr_t H5O_open(H5O_loc_t *loc);
H5_DLL herr_t H5O_close(H5O_loc_t *loc);
H5_DLL int H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id);
-H5_DLL int H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, unsigned *oh_flags);
-H5_DLL H5O_t *H5O_pin(H5O_loc_t *loc, hid_t dxpl_id);
+H5_DLL H5O_t *H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, H5AC_protect_t prot);
+H5_DLL H5O_t *H5O_pin(const H5O_loc_t *loc, hid_t dxpl_id);
H5_DLL herr_t H5O_unpin(H5O_t *oh);
+H5_DLL herr_t H5O_unprotect(const H5O_loc_t *loc, hid_t dxpl_id, H5O_t *oh,
+ unsigned oh_flags);
H5_DLL herr_t H5O_touch(const H5O_loc_t *loc, hbool_t force, hid_t dxpl_id);
H5_DLL herr_t H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
hbool_t force);
diff --git a/src/H5Oshared.c b/src/H5Oshared.c
index cdd9778..4a9c2bb 100644
--- a/src/H5Oshared.c
+++ b/src/H5Oshared.c
@@ -256,12 +256,12 @@ H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
* is possible, for example, if an attribute's datatype is shared in
* the same object header the attribute is in. Adjust the link
* count directly. */
- unsigned oh_flags = H5AC__NO_FLAGS_SET; /* This is used only to satisfy H5O_link_oh */
+ hbool_t deleted = FALSE; /* This is used only to satisfy H5O_link_oh */
- if(H5O_link_oh(f, adjust, dxpl_id, open_oh, &oh_flags) < 0)
+ if(H5O_link_oh(f, adjust, dxpl_id, open_oh, &deleted) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count")
- HDassert(!(oh_flags & H5AC__DELETED_FLAG));
+ HDassert(!deleted);
} else
/* The shared message is in another object header */
if(H5O_link(&oloc, adjust, dxpl_id) < 0)
diff --git a/src/H5Otest.c b/src/H5Otest.c
index 041194a..77b7540 100644
--- a/src/H5Otest.c
+++ b/src/H5Otest.c
@@ -98,7 +98,7 @@ H5O_is_attr_dense_test(hid_t oid)
{
H5O_t *oh = NULL; /* Object header */
H5O_ainfo_t ainfo; /* Attribute information for object */
- H5O_loc_t *loc; /* Pointer to object's location */
+ H5O_loc_t *loc; /* Pointer to object's location */
htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5O_is_attr_dense_test, FAIL)
@@ -108,7 +108,7 @@ H5O_is_attr_dense_test(hid_t oid)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -130,7 +130,7 @@ H5O_is_attr_dense_test(hid_t oid)
ret_value = FALSE;
done:
- if(oh && H5AC_unprotect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, H5AC_ind_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -173,7 +173,7 @@ H5O_is_attr_empty_test(hid_t oid)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -217,7 +217,7 @@ done:
/* Release resources */
if(bt2_name && H5B2_close(bt2_name, H5AC_ind_dxpl_id) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for name index")
- if(oh && H5AC_unprotect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, H5AC_ind_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -260,7 +260,7 @@ H5O_num_attrs_test(hid_t oid, hsize_t *nattrs)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -301,7 +301,7 @@ done:
/* Release resources */
if(bt2_name && H5B2_close(bt2_name, H5AC_ind_dxpl_id) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for name index")
- if(oh && H5AC_unprotect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, H5AC_ind_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -346,7 +346,7 @@ H5O_attr_dense_info_test(hid_t oid, hsize_t *name_count, hsize_t *corder_count)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -390,7 +390,7 @@ done:
HDONE_ERROR(H5E_OHDR, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for name index")
if(bt2_corder && H5B2_close(bt2_corder, H5AC_ind_dxpl_id) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for creation order index")
- if(oh && H5AC_unprotect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, H5AC_ind_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -434,7 +434,7 @@ H5O_check_msg_marked_test(hid_t oid, hbool_t flag_val)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(loc, H5AC_ind_dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
/* Locate "unknown" message */
@@ -453,9 +453,68 @@ H5O_check_msg_marked_test(hid_t oid, hbool_t flag_val)
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "'unknown' message type not found")
done:
- if(oh && H5AC_unprotect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(loc, H5AC_ind_dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_check_msg_marked_test() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5O_expunge_chunks_test
+ PURPOSE
+ Expunge all the chunks for an object header from the cache.
+ USAGE
+ herr_t H5O_expunge_chunks_test(f, dxpl_id, loc)
+ H5F_t *f; IN: Pointer to file that object is within
+ hid_t dxpl_id; IN: DXPL to use for operation
+ H5O_loc_t *loc; IN: Object location for object header to expunge
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Iterates over all the chunks for an object header an expunges each from the
+ metadata cache.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5O_expunge_chunks_test(const H5O_loc_t *loc, hid_t dxpl_id)
+{
+ H5O_t *oh = NULL; /* Object header */
+ haddr_t chk_addr[16]; /* Array of chunk addresses */
+ unsigned nchunks; /* Number of chunks in object header */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_expunge_chunks_test, FAIL)
+
+ /* Get the object header */
+ if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
+
+ /* Safety check */
+ nchunks = oh->nchunks;
+ HDassert(nchunks < NELMTS(chk_addr));
+
+ /* Iterate over all the chunks, saving the chunk addresses */
+ for(u = 0; u < oh->nchunks; u++)
+ chk_addr[u] = oh->chunk[u].addr;
+
+ /* Release the object header */
+ if(H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header")
+
+ /* Iterate over all the saved chunk addresses, evicting them from the cache */
+ /* (in reverse order, so that chunk #0 is unpinned) */
+ for(u = nchunks - 1; u < nchunks; u--)
+ if(H5AC_expunge_entry(loc->file, dxpl_id, (u == 0 ? H5AC_OHDR : H5AC_OHDR_CHK), chk_addr[u], H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTEXPUNGE, FAIL, "unable to expunge object header chunk")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_expunge_chunks_test() */
+
diff --git a/src/H5R.c b/src/H5R.c
index d335fce..d14b9fc 100644
--- a/src/H5R.c
+++ b/src/H5R.c
@@ -366,8 +366,9 @@ H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_re
H5O_loc_t oloc; /* Object location */
H5G_name_t path; /* Path of object */
H5G_loc_t loc; /* Group location */
+ unsigned rc; /* Reference count of object */
H5O_type_t obj_type; /* Type of object */
- hid_t ret_value;
+ hid_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5R_dereference)
@@ -415,8 +416,9 @@ H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_re
HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
} /* end switch */
- /* Check to make certain that this object hasn't been deleted since the reference was created */
- if(H5O_link(&oloc, 0, dxpl_id) <= 0)
+ /* Get the # of links for object, and its type */
+ /* (To check to make certain that this object hasn't been deleted since the reference was created) */
+ if(H5O_get_rc_and_type(&oloc, dxpl_id, &rc, &obj_type) < 0 || 0 == rc)
HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, FAIL, "dereferencing deleted object")
/* Construct a group location for opening the object */
@@ -424,10 +426,6 @@ H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_re
loc.oloc = &oloc;
loc.path = &path;
- /* Get the type of the object */
- if(H5O_obj_type(&oloc, &obj_type, dxpl_id) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to get object type")
-
/* Open the object */
switch(obj_type) {
case H5O_TYPE_GROUP:
@@ -688,6 +686,7 @@ H5R_get_obj_type(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type,
const void *_ref, H5O_type_t *obj_type)
{
H5O_loc_t oloc; /* Object location */
+ unsigned rc; /* Reference count of object */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5R_get_obj_type)
@@ -736,14 +735,11 @@ H5R_get_obj_type(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type,
HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
} /* end switch */
- /* Check to make certain that this object hasn't been deleted since the reference was created */
- if(H5O_link(&oloc, 0, dxpl_id) <= 0)
+ /* Get the # of links for object, and its type */
+ /* (To check to make certain that this object hasn't been deleted since the reference was created) */
+ if(H5O_get_rc_and_type(&oloc, dxpl_id, &rc, obj_type) < 0 || 0 == rc)
HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, FAIL, "dereferencing deleted object")
- /* Get the object type */
- if(H5O_obj_type(&oloc, obj_type, dxpl_id) < 0)
- HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "unable to get object type")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5R_get_obj_type() */
diff --git a/src/H5SM.c b/src/H5SM.c
index b2468d3..79e756b 100755
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -25,7 +25,6 @@
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
#include "H5FLprivate.h" /* Free Lists */
@@ -2247,7 +2246,7 @@ H5SM_read_mesg(H5F_t *f, const H5SM_sohm_t *mesg, H5HF_t *fheap,
HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, FAIL, "unable to open object header")
/* Load the object header from the cache */
- if(NULL == (oh = (H5O_t *)H5AC_protect(oloc.file, dxpl_id, H5AC_OHDR, oloc.addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = H5O_protect(&oloc, dxpl_id, H5AC_READ)))
HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load object header")
} /* end if */
else
@@ -2276,7 +2275,7 @@ H5SM_read_mesg(H5F_t *f, const H5SM_sohm_t *mesg, H5HF_t *fheap,
done:
/* Close the object header if we opened one and had an error */
if(oh && oh != open_oh) {
- if(H5AC_unprotect(oloc.file, dxpl_id, H5AC_OHDR, oloc.addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ if(oh && H5O_unprotect(&oloc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
if(H5O_close(&oloc) < 0)
HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "unable to close object header")
diff --git a/src/Makefile.am b/src/Makefile.am
index 9acfcd2..65e2bac 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -76,7 +76,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \
H5MM.c H5MP.c H5MPtest.c \
H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \
- H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c \
+ H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c H5Ochunk.c \
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \
H5Ofill.c H5Ofsinfo.c H5Oginfo.c \
H5Olayout.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index 1358bc4..7c726ce 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -126,7 +126,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
H5Lexternal.lo H5lib_settings.lo H5MF.lo H5MFaggr.lo \
H5MFdbg.lo H5MFsection.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \
H5Oainfo.lo H5Oalloc.lo H5Oattr.lo H5Oattribute.lo H5Obogus.lo \
- H5Obtreek.lo H5Ocache.lo H5Ocont.lo H5Ocopy.lo H5Odbg.lo \
+ H5Obtreek.lo H5Ocache.lo H5Ochunk.lo H5Ocont.lo H5Ocopy.lo H5Odbg.lo \
H5Odrvinfo.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Ofsinfo.lo \
H5Oginfo.lo H5Olayout.lo H5Olinfo.lo H5Olink.lo H5Omessage.lo \
H5Omtime.lo H5Oname.lo H5Onull.lo H5Opline.lo H5Orefcount.lo \
@@ -494,7 +494,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \
H5MM.c H5MP.c H5MPtest.c \
H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \
- H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c \
+ H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c H5Ochunk.c \
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \
H5Ofill.c H5Ofsinfo.c H5Oginfo.c \
H5Olayout.c \
@@ -818,6 +818,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Obogus.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Obtreek.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ocache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ochunk.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ocont.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ocopy.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Odbg.Plo@am__quote@