diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2009-03-24 19:23:11 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2009-03-24 19:23:11 (GMT) |
commit | 53e4b5b90b3f5cb9dc7fbe47e6787a5280b2fa04 (patch) | |
tree | 825d37444aa8c0f3bab4442c3f1b0068c7ac2924 /src | |
parent | 65dc3358db37b04cc64b65b88065cbaf48e63a8b (diff) | |
download | hdf5-53e4b5b90b3f5cb9dc7fbe47e6787a5280b2fa04.zip hdf5-53e4b5b90b3f5cb9dc7fbe47e6787a5280b2fa04.tar.gz hdf5-53e4b5b90b3f5cb9dc7fbe47e6787a5280b2fa04.tar.bz2 |
[svn-r16601] Description:
Bring r16536:16600 from trunk back into revise_chunks branch
Tested on:
FreeBSD/32 6.3 (duty) in debug mode
FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode
Linux/32 2.6 (jam) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe,
in debug mode
Linux/64-amd64 2.6 (smirom) 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 production mode
Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode
Mac OS X/32 10.5.6 (amazon) in debug mode
Mac OS X/32 10.5.6 (amazon) w/C++ & FORTRAN, w/threadsafe,
in production mode
Diffstat (limited to 'src')
49 files changed, 1570 insertions, 962 deletions
@@ -2288,10 +2288,10 @@ H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, { herr_t result; herr_t ret_value=SUCCEED; /* Return value */ - hbool_t size_changed = FALSE; hbool_t dirtied; size_t new_size = 0; #ifdef H5_HAVE_PARALLEL + hbool_t size_changed = FALSE; H5AC_aux_t * aux_ptr = NULL; #endif /* H5_HAVE_PARALLEL */ #if H5AC__TRACE_FILE_ENABLED @@ -2345,7 +2345,9 @@ H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, if ( ((H5AC_info_t *)thing)->size != new_size ) { +#ifdef H5_HAVE_PARALLEL size_changed = TRUE; +#endif /* H5_HAVE_PARALLEL */ flags = flags | H5AC__SIZE_CHANGED_FLAG; #if H5AC__TRACE_FILE_ENABLED trace_flags = flags; diff --git a/src/H5Aint.c b/src/H5Aint.c index c7013a2..2ac17fa 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -716,7 +716,7 @@ H5A_get_ainfo(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_ainfo_t *ainfo) /* Retrieve # of records in "name" B-tree */ /* (should be same # of records in all indices) */ if(H5B2_get_nrec(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &ainfo->nattrs) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't retrieve # of records in index") + HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index") } /* end if */ else /* Retrieve # of attributes from object header */ @@ -2057,3 +2057,47 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5B_get_info() */ +#ifndef H5_STRICT_FORMAT_CHECKS + +/*------------------------------------------------------------------------- + * Function: H5B_valid + * + * Purpose: Attempt to load a b-tree node. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * March 17, 2009 + * + *------------------------------------------------------------------------- + */ +htri_t +H5B_valid(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr) +{ + H5B_t *bt; /* The btree */ + htri_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5B_valid, FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(type); + + if(!H5F_addr_defined(addr)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "address is undefined") + + /* Protect the node */ + if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node") + + /* Release the node */ + if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5B_valid() */ +#endif /* H5_STRICT_FORMAT_CHECKS */ + diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h index 93c2d80..2ec2c22 100644 --- a/src/H5Bprivate.h +++ b/src/H5Bprivate.h @@ -168,5 +168,9 @@ H5_DLL H5B_shared_t *H5B_shared_new(const H5F_t *f, const H5B_class_t *type, H5_DLL herr_t H5B_shared_free(void *_shared); H5_DLL herr_t H5B_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int fwidth, const H5B_class_t *type, void *udata); +#ifndef H5_STRICT_FORMAT_CHECKS +H5_DLL htri_t H5B_valid(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, + haddr_t addr); +#endif /* H5_STRICT_FORMAT_CHECKS */ #endif /* _H5Bprivate_H */ @@ -3147,6 +3147,10 @@ H5C_create(size_t max_cache_size, cache_ptr->epoch_marker_ringbuf_last = 0; cache_ptr->epoch_marker_ringbuf_size = 0; + /* Initialize all epoch marker entries' fields to zero/FALSE/NULL */ + HDmemset(cache_ptr->epoch_markers, 0, sizeof(cache_ptr->epoch_markers)); + + /* Set non-zero/FALSE/NULL fields for epoch markers */ for ( i = 0; i < H5C__MAX_EPOCH_MARKERS; i++ ) { (cache_ptr->epoch_marker_active)[i] = FALSE; @@ -3155,27 +3159,7 @@ H5C_create(size_t max_cache_size, H5C__H5C_CACHE_ENTRY_T_MAGIC; #endif /* NDEBUG */ ((cache_ptr->epoch_markers)[i]).addr = (haddr_t)i; - ((cache_ptr->epoch_markers)[i]).size = (size_t)0; ((cache_ptr->epoch_markers)[i]).type = &epoch_marker_class; - ((cache_ptr->epoch_markers)[i]).is_dirty = FALSE; - ((cache_ptr->epoch_markers)[i]).dirtied = FALSE; - ((cache_ptr->epoch_markers)[i]).is_protected = FALSE; - ((cache_ptr->epoch_markers)[i]).is_read_only = FALSE; - ((cache_ptr->epoch_markers)[i]).ro_ref_count = 0; - ((cache_ptr->epoch_markers)[i]).is_pinned = FALSE; - ((cache_ptr->epoch_markers)[i]).in_slist = FALSE; - ((cache_ptr->epoch_markers)[i]).ht_next = NULL; - ((cache_ptr->epoch_markers)[i]).ht_prev = NULL; - ((cache_ptr->epoch_markers)[i]).next = NULL; - ((cache_ptr->epoch_markers)[i]).prev = NULL; - ((cache_ptr->epoch_markers)[i]).aux_next = NULL; - ((cache_ptr->epoch_markers)[i]).aux_prev = NULL; -#if H5C_COLLECT_CACHE_ENTRY_STATS - ((cache_ptr->epoch_markers)[i]).accesses = 0; - ((cache_ptr->epoch_markers)[i]).clears = 0; - ((cache_ptr->epoch_markers)[i]).flushes = 0; - ((cache_ptr->epoch_markers)[i]).pins = 0; -#endif /* H5C_COLLECT_CACHE_ENTRY_STATS */ } if ( H5C_reset_cache_hit_rate_stats(cache_ptr) != SUCCEED ) { @@ -3824,222 +3808,244 @@ H5C_flush_cache(H5F_t * f, ( protected_entries == 0 ) && ( flushed_entries_last_pass ) ) { - flushed_entries_last_pass = FALSE; - node_ptr = H5SL_first(cache_ptr->slist_ptr); + unsigned curr_flush_dep_height = 0; + unsigned flush_dep_passes = 0; - if ( node_ptr != NULL ) { + flushed_entries_last_pass = FALSE; - next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); + /* Loop over all flush dependency heights of entries */ + while((curr_flush_dep_height <= H5C__NUM_FLUSH_DEP_HEIGHTS) && + (cache_ptr->slist_len != 0) && + (flush_dep_passes < H5C__MAX_PASSES_ON_FLUSH) ) + { + hbool_t flushed_during_dep_loop = FALSE; - if ( next_entry_ptr == NULL ) { + /* Start at beginning of skip list each time */ + node_ptr = H5SL_first(cache_ptr->slist_ptr); + HDassert( node_ptr != NULL ); - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "next_entry_ptr == NULL 1 ?!?!"); - } -#ifndef NDEBUG - HDassert( next_entry_ptr->magic == - H5C__H5C_CACHE_ENTRY_T_MAGIC ); -#endif /* NDEBUG */ - HDassert( next_entry_ptr->is_dirty ); + /* Get cache entry for this node */ + next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); + if ( NULL == next_entry_ptr ) + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "next_entry_ptr == NULL ?!?!") + HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC ); + HDassert( next_entry_ptr->is_dirty ); HDassert( next_entry_ptr->in_slist ); - } else { - - next_entry_ptr = NULL; - - } - - HDassert( node_ptr != NULL ); - #if H5C_DO_SANITY_CHECKS - /* For sanity checking, try to verify that the skip list has - * the expected size and number of entries at the end of each - * internal while loop (see below). - * - * Doing this get a bit tricky, as depending on flags, we may - * or may not flush all the entries in the slist. - * - * To make things more entertaining, with the advent of the - * fractal heap, the entry flush callback can cause entries - * to be dirtied, resized, and/or renamed. - * - * To deal with this, we first make note of the initial - * skip list length and size: - */ - initial_slist_len = cache_ptr->slist_len; - initial_slist_size = cache_ptr->slist_size; + /* For sanity checking, try to verify that the skip list has + * the expected size and number of entries at the end of each + * internal while loop (see below). + * + * Doing this get a bit tricky, as depending on flags, we may + * or may not flush all the entries in the slist. + * + * To make things more entertaining, with the advent of the + * fractal heap, the entry flush callback can cause entries + * to be dirtied, resized, and/or renamed. + * + * To deal with this, we first make note of the initial + * skip list length and size: + */ + initial_slist_len = cache_ptr->slist_len; + initial_slist_size = cache_ptr->slist_size; - /* We then zero counters that we use to track the number - * and total size of entries flushed: - */ - flushed_entries_count = 0; - flushed_entries_size = 0; - - /* As mentioned above, there is the possibility that - * entries will be dirtied, resized, and/or flushed during - * our pass through the skip list. To capture the number - * of entries added, and the skip list size delta, - * zero the slist_len_increase and slist_size_increase of - * the cache's instance of H5C_t. These fields will be - * updated elsewhere to account for slist insertions and/or - * dirty entry size changes. - */ - cache_ptr->slist_len_increase = 0; - cache_ptr->slist_size_increase = 0; + /* We then zero counters that we use to track the number + * and total size of entries flushed: + */ + flushed_entries_count = 0; + flushed_entries_size = 0; + + /* As mentioned above, there is the possibility that + * entries will be dirtied, resized, and/or flushed during + * our pass through the skip list. To capture the number + * of entries added, and the skip list size delta, + * zero the slist_len_increase and slist_size_increase of + * the cache's instance of H5C_t. These fields will be + * updated elsewhere to account for slist insertions and/or + * dirty entry size changes. + */ + cache_ptr->slist_len_increase = 0; + cache_ptr->slist_size_increase = 0; - /* at the end of the loop, use these values to compute the - * expected slist length and size and compare this with the - * value recorded in the cache's instance of H5C_t. - */ + /* at the end of the loop, use these values to compute the + * expected slist length and size and compare this with the + * value recorded in the cache's instance of H5C_t. + */ #endif /* H5C_DO_SANITY_CHECKS */ - while ( node_ptr != NULL ) - { - entry_ptr = next_entry_ptr; - - /* With the advent of the fractal heap, it is possible - * that the flush callback will dirty and/or resize - * other entries in the cache. In particular, while - * Quincey has promised me that this will never happen, - * it is possible that the flush callback for an - * entry may protect an entry that is not in the cache, - * perhaps causing the cache to flush and possibly - * evict the entry associated with node_ptr to make - * space for the new entry. - * - * Thus we do a bit of extra sanity checking on entry_ptr, - * and break out of this scan of the skip list if we - * detect minor problems. We have a bit of leaway on the - * number of passes though the skip list, so this shouldn't - * be an issue in the flush in and of itself, as it should - * be all but impossible for this to happen more than once - * in any flush. - * - * Observe that that breaking out of the scan early - * shouldn't break the sanity checks just after the end - * of this while loop. - * - * If an entry has merely been marked clean and removed from - * the s-list, we simply break out of the scan. - * - * If the entry has been evicted, we flag an error and - * exit. - */ + while ( node_ptr != NULL ) + { + entry_ptr = next_entry_ptr; + + /* With the advent of the fractal heap, it is possible + * that the flush callback will dirty and/or resize + * other entries in the cache. In particular, while + * Quincey has promised me that this will never happen, + * it is possible that the flush callback for an + * entry may protect an entry that is not in the cache, + * perhaps causing the cache to flush and possibly + * evict the entry associated with node_ptr to make + * space for the new entry. + * + * Thus we do a bit of extra sanity checking on entry_ptr, + * and break out of this scan of the skip list if we + * detect minor problems. We have a bit of leaway on the + * number of passes though the skip list, so this shouldn't + * be an issue in the flush in and of itself, as it should + * be all but impossible for this to happen more than once + * in any flush. + * + * Observe that that breaking out of the scan early + * shouldn't break the sanity checks just after the end + * of this while loop. + * + * If an entry has merely been marked clean and removed from + * the s-list, we simply break out of the scan. + * + * If the entry has been evicted, we flag an error and + * exit. + */ #ifndef NDEBUG - if ( entry_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) { + if ( entry_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) { - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "entry_ptr->magic invalid ?!?!"); + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "entry_ptr->magic invalid ?!?!"); - } else + } else #endif /* NDEBUG */ - if ( ( ! entry_ptr->is_dirty ) || - ( ! entry_ptr->in_slist ) ) { + if ( ( ! entry_ptr->is_dirty ) || + ( ! entry_ptr->in_slist ) ) { - /* the s-list has been modified out from under us. - * set node_ptr to NULL and break out of the loop. - */ - node_ptr = NULL; - break; - } + /* the s-list has been modified out from under us. + * set node_ptr to NULL and break out of the inner loop. + */ + node_ptr = NULL; + goto end_of_inner_loop;; + } - /* increment node pointer now, before we delete its target - * from the slist. - */ - node_ptr = H5SL_next(node_ptr); + /* increment node pointer now, before we delete its target + * from the slist. + */ + node_ptr = H5SL_next(node_ptr); - if ( node_ptr != NULL ) { - next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); + if ( node_ptr != NULL ) { + next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); - if ( next_entry_ptr == NULL ) { - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "next_entry_ptr == NULL 2 ?!?!"); + if ( next_entry_ptr == NULL ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "next_entry_ptr == NULL 2 ?!?!"); + } + HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC ); + HDassert( next_entry_ptr->is_dirty ); + HDassert( next_entry_ptr->in_slist ); + } else { + next_entry_ptr = NULL; } -#ifndef NDEBUG - HDassert( next_entry_ptr->magic == - H5C__H5C_CACHE_ENTRY_T_MAGIC ); -#endif /* NDEBUG */ - HDassert( next_entry_ptr->is_dirty ); - HDassert( next_entry_ptr->in_slist ); - } else { - next_entry_ptr = NULL; - } - HDassert( entry_ptr != NULL ); - HDassert( entry_ptr->in_slist ); + HDassert( entry_ptr != NULL ); + HDassert( entry_ptr->in_slist ); - if ( ( ! flush_marked_entries ) || - ( entry_ptr->flush_marker ) ) { + if ( ( ! flush_marked_entries ) || + ( entry_ptr->flush_marker ) ) { - if ( entry_ptr->is_protected ) { + if ( entry_ptr->is_protected ) { - /* we probably have major problems -- but lets flush - * everything we can before we decide whether to flag - * an error. - */ - tried_to_flush_protected_entry = TRUE; - protected_entries++; - - } else if ( entry_ptr->is_pinned ) { - /* Test to see if we are can flush the entry now. - * If we can, go ahead and flush. Note that we - * aren't trying to do a destroy here, so that - * is not an issue. - */ - if ( TRUE ) { /* When we get to multithreaded cache, - * we will need either locking code, - * and/or a test to see if the entry - * is in flushable condition here. - */ + /* we probably have major problems -- but lets flush + * everything we can before we decide whether to flag + * an error. + */ + tried_to_flush_protected_entry = TRUE; + protected_entries++; + + } else if ( entry_ptr->is_pinned ) { + /* Test to see if we are can flush the entry now. + * If we can, go ahead and flush. Note that we + * aren't trying to do a destroy here, so that + * is not an issue. + */ + if(entry_ptr->flush_dep_height == curr_flush_dep_height ) { #if H5C_DO_SANITY_CHECKS - flushed_entries_count++; - flushed_entries_size += entry_ptr->size; + flushed_entries_count++; + flushed_entries_size += entry_ptr->size; #endif /* H5C_DO_SANITY_CHECKS */ - status = H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - cache_ptr, - NULL, - entry_ptr->addr, - flags, - &first_flush, - FALSE); - if ( status < 0 ) { - - /* This shouldn't happen -- if it does, we are - * toast so just scream and die. - */ - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "dirty pinned entry flush failed.") - } - flushed_entries_last_pass = TRUE; - } - } else { + status = H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + cache_ptr, + NULL, + entry_ptr->addr, + flags, + &first_flush, + FALSE); + if ( status < 0 ) { + + /* This shouldn't happen -- if it does, we are + * toast so just scream and die. + */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "dirty pinned entry flush failed.") + } + flushed_during_dep_loop = TRUE; + } /* end if */ + else if(entry_ptr->flush_dep_height < curr_flush_dep_height) + /* This shouldn't happen -- if it does, just scream and die. */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry below current flush dep. height.") + } else { + /* Test to see if we are can flush the entry now. + * If we can, go ahead and flush. Note that we + * aren't trying to do a destroy here, so that + * is not an issue. + */ + if(entry_ptr->flush_dep_height == curr_flush_dep_height ){ #if H5C_DO_SANITY_CHECKS - flushed_entries_count++; - flushed_entries_size += entry_ptr->size; + flushed_entries_count++; + flushed_entries_size += entry_ptr->size; #endif /* H5C_DO_SANITY_CHECKS */ - status = H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - cache_ptr, - NULL, - entry_ptr->addr, - flags, - &first_flush, - FALSE); - if ( status < 0 ) { + status = H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + cache_ptr, + NULL, + entry_ptr->addr, + flags, + &first_flush, + FALSE); + if ( status < 0 ) { + + /* This shouldn't happen -- if it does, we are + * toast so just scream and die. + */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Can't flush entry.") + } + flushed_during_dep_loop = TRUE; + } /* end if */ + else if(entry_ptr->flush_dep_height < curr_flush_dep_height) + /* This shouldn't happen -- if it does, just scream and die. */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry below current flush dep. height.") + } /* end else */ + } /* end if */ + } /* while ( node_ptr != NULL ) */ + + /* Check for incrementing flush dependency height */ + if(flushed_during_dep_loop) { + /* If we flushed an entry at this flush dependency height + * start over at the bottom level of the flush dependencies + */ + curr_flush_dep_height = 0; - /* This shouldn't happen -- if it does, we are - * toast so just scream and die. - */ - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "Can't flush entry.") - } - flushed_entries_last_pass = TRUE; - } - } - } /* while ( node_ptr != NULL ) */ + /* Make certain we don't get stuck in an infinite loop */ + flush_dep_passes++; + + /* Set flag for outer loop */ + flushed_entries_last_pass = TRUE; + } /* end if */ + else + curr_flush_dep_height++; + + } /* while ( curr_flush_dep_height <= H5C__NUM_FLUSH_DEP_HEIGHTS) */ +end_of_inner_loop: #if H5C_DO_SANITY_CHECKS /* Verify that the slist size and length are as expected. */ @@ -4802,9 +4808,7 @@ H5C_insert_entry(H5F_t * f, void * thing, unsigned int flags) { - /* const char * fcn_name = "H5C_insert_entry()"; */ herr_t result; - herr_t ret_value = SUCCEED; /* Return value */ hbool_t first_flush = TRUE; hbool_t insert_pinned; hbool_t set_flush_marker; @@ -4812,6 +4816,8 @@ H5C_insert_entry(H5F_t * f, size_t empty_space; H5C_cache_entry_t * entry_ptr; H5C_cache_entry_t * test_entry_ptr; + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5C_insert_entry, FAIL) @@ -4900,6 +4906,12 @@ H5C_insert_entry(H5F_t * f, entry_ptr->destroy_in_progress = FALSE; entry_ptr->free_file_space_on_destroy = FALSE; + /* Initialize flush dependency height fields */ + entry_ptr->flush_dep_parent = NULL; + for(u = 0; u < H5C__NUM_FLUSH_DEP_HEIGHTS; u++) + entry_ptr->child_flush_dep_height_rc[u] = 0; + entry_ptr->flush_dep_height = 0; + entry_ptr->ht_next = NULL; entry_ptr->ht_prev = NULL; @@ -7661,20 +7673,14 @@ H5C_stats__reset(H5C_t UNUSED * cache_ptr) /*------------------------------------------------------------------------- * Function: H5C_unpin_entry() * - * Purpose: Unpin a cache entry. The entry must be unprotected at - * the time of call, and must be pinned. + * Purpose: Unpin a cache entry. The entry can be either protected or + * unprotected at the time of call, but must be pinned. * * Return: Non-negative on success/Negative on failure * * Programmer: John Mainzer * 3/22/06 * - * Modifications: - * - * JRM -- 4/26/06 - * Modified routine to allow it to operate on protected - * entries. - * *------------------------------------------------------------------------- */ herr_t @@ -8490,6 +8496,342 @@ done: } /* H5C_validate_resize_config() */ +/*------------------------------------------------------------------------- + * Function: H5C_adjust_flush_dependency_rc() + * + * Purpose: "Atomicly" adjust flush dependency ref. counts for an entry, + * as a result of a flush dependency child's height changing. + * + * Note: Entry will remain in flush dependency relationship with its + * child entry (i.e. it's not going to get unpinned as a result + * of this change), but change could trickle upward, if this + * entry's height changes and it has a flush dependency parent. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * 3/05/09 + * + *------------------------------------------------------------------------- + */ +static void +H5C_adjust_flush_dependency_rc(H5C_cache_entry_t * cache_entry, + unsigned old_child_height, unsigned new_child_height) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5C_adjust_flush_dependency_rc) + + /* Sanity checks */ + HDassert(cache_entry); + HDassert(cache_entry->is_pinned); + HDassert(cache_entry->flush_dep_height > 0); + HDassert(cache_entry->flush_dep_height < H5C__NUM_FLUSH_DEP_HEIGHTS); + HDassert(cache_entry->child_flush_dep_height_rc[old_child_height] > 0); + HDassert(old_child_height < H5C__NUM_FLUSH_DEP_HEIGHTS); + HDassert(old_child_height != new_child_height); + HDassert(new_child_height < H5C__NUM_FLUSH_DEP_HEIGHTS); + + /* Adjust ref. counts for entry's flush dependency children heights */ + cache_entry->child_flush_dep_height_rc[new_child_height]++; + cache_entry->child_flush_dep_height_rc[old_child_height]--; + + /* Check for flush dependency height of entry increasing */ + if((new_child_height + 1) > cache_entry->flush_dep_height) { + + /* Check if entry has _its_ own parent flush dependency entry */ + if(NULL != cache_entry->flush_dep_parent) { + /* Adjust flush dependency ref. counts on entry's parent */ + H5C_adjust_flush_dependency_rc(cache_entry->flush_dep_parent, cache_entry->flush_dep_height, new_child_height + 1); + } /* end if */ + + /* Set new flush dependency height of entry */ + cache_entry->flush_dep_height = new_child_height + 1; + } /* end if */ + else { + /* Check for child's flush dep. height decreasing and ref. count of + * old child height going to zero, it could mean the parent's + * flush dependency height dropped. + */ + if((new_child_height < old_child_height) + && ((old_child_height + 1) == cache_entry->flush_dep_height) + && (0 == cache_entry->child_flush_dep_height_rc[old_child_height])) { + int i; /* Local index variable */ + + /* Re-scan child flush dependency height ref. counts to determine + * this entry's height. + */ +#ifndef NDEBUG + for(i = (H5C__NUM_FLUSH_DEP_HEIGHTS - 1); i > (int)new_child_height; i--) + HDassert(0 == cache_entry->child_flush_dep_height_rc[i]); +#endif /* NDEBUG */ + for(i = (int)new_child_height; i >= 0; i--) + /* Check for child flush dependencies of this height */ + if(cache_entry->child_flush_dep_height_rc[i] > 0) + break; + + /* Sanity checks */ + HDassert((unsigned)(i + 1) < cache_entry->flush_dep_height); + + /* Check if entry has _its_ own parent flush dependency entry */ + if(NULL != cache_entry->flush_dep_parent) { + /* Adjust flush dependency ref. counts on entry's parent */ + H5C_adjust_flush_dependency_rc(cache_entry->flush_dep_parent, cache_entry->flush_dep_height, (unsigned)(i + 1)); + } /* end if */ + + /* Set new flush dependency height of entry */ + cache_entry->flush_dep_height = (unsigned)(i + 1); + } /* end if */ + } /* end else */ + + + /* Post-conditions, for successful operation */ + HDassert(cache_entry->is_pinned); + HDassert(cache_entry->flush_dep_height > 0); + HDassert(cache_entry->flush_dep_height <= H5C__NUM_FLUSH_DEP_HEIGHTS); + HDassert(cache_entry->child_flush_dep_height_rc[new_child_height] > 0); + + FUNC_LEAVE_NOAPI_VOID +} /* H5C_adjust_flush_dependency_rc() */ + + +/*------------------------------------------------------------------------- + * Function: H5C_create_flush_dependency() + * + * Purpose: Initiates a parent<->child entry flush dependency. The parent + * entry must be protected at the time of call, and must have all + * dependencies removed before the cache can shut down. + * + * Note: Flush dependencies in the cache indicate that a child entry + * must be flushed to the file before its parent. (This is + * currently used to implement Single-Writer/Multiple-Reader (SWMR) + * I/O access for data structures in the file). + * + * Each child entry can have only one parent entry, but parent + * entries can have >1 child entries. The flush dependency + * height of a parent entry is one greater than the max. flush + * dependency height of its children. + * + * Creating a flush dependency between two entries will also pin + * the parent entry. (The parent entry must _not_ be pinned + * through some other mechanism) + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * 3/05/09 + * + *------------------------------------------------------------------------- + */ +#ifndef NDEBUG +herr_t +H5C_create_flush_dependency(H5C_t * cache_ptr, void * parent_thing, + void * child_thing) +#else +herr_t +H5C_create_flush_dependency(H5C_t UNUSED * cache_ptr, void * parent_thing, + void * child_thing) +#endif +{ + H5C_cache_entry_t * parent_entry = (H5C_cache_entry_t *)parent_thing; /* Ptr to parent thing's entry */ + H5C_cache_entry_t * child_entry = (H5C_cache_entry_t *)child_thing; /* Ptr to child thing's entry */ +#ifndef NDEBUG + unsigned prev_flush_dep_height = parent_entry->flush_dep_height; /* Previous flush height for parent entry */ +#endif /* NDEBUG */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C_create_flush_dependency, FAIL) + + /* Sanity checks */ + HDassert(cache_ptr); + HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); + HDassert(parent_entry); + HDassert(parent_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); + HDassert(parent_entry->flush_dep_height <= H5C__NUM_FLUSH_DEP_HEIGHTS); + HDassert(H5F_addr_defined(parent_entry->addr)); + HDassert(child_entry); + HDassert(child_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); + HDassert(H5F_addr_defined(child_entry->addr)); + HDassert(child_entry->flush_dep_height <= H5C__NUM_FLUSH_DEP_HEIGHTS); + + /* More sanity checks */ + if(child_entry == parent_entry) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Child entry flush dependency parent can't be itself") + if(!parent_entry->is_protected) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Parent entry isn't protected") + if(NULL != child_entry->flush_dep_parent) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Child entry already has flush dependency parent") + { + H5C_cache_entry_t *tmp_entry = parent_entry; /* Temporary cache entry in flush dependency chain */ + unsigned tmp_flush_height = 0; /* Different in heights of parent entry */ + + /* Find the top entry in the flush dependency list */ + while(NULL != tmp_entry->flush_dep_parent) { + tmp_flush_height++; + tmp_entry = tmp_entry->flush_dep_parent; + } /* end while */ + + /* Check if we will make the dependency chain too long */ + if((tmp_flush_height + child_entry->flush_dep_height + 1) + > H5C__NUM_FLUSH_DEP_HEIGHTS) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Combined flush dependency height too large") + } + + /* Check for parent already pinned */ + if(parent_entry->is_pinned) { + /* Verify that the parent entry was pinned through a flush dependency relationship */ + if(0 == parent_entry->flush_dep_height) + HGOTO_ERROR(H5E_CACHE, H5E_CANTDEPEND, FAIL, "Parent entry wasn't pinned through flush dependency") + } /* end if */ + else { + /* Sanity check */ + HDassert(parent_entry->flush_dep_height == 0); + + /* Pin the parent entry */ + parent_entry->is_pinned = TRUE; + H5C__UPDATE_STATS_FOR_PIN(cache_ptr, parent_entry) + } /* end else */ + + /* Increment ref. count for parent's flush dependency children heights */ + parent_entry->child_flush_dep_height_rc[child_entry->flush_dep_height]++; + + /* Check for increasing parent flush dependency height */ + if((child_entry->flush_dep_height + 1) > parent_entry->flush_dep_height) { + + /* Check if parent entry has _its_ own parent flush dependency entry */ + if(NULL != parent_entry->flush_dep_parent) { + /* Adjust flush dependency ref. counts on parent entry's parent */ + H5C_adjust_flush_dependency_rc(parent_entry->flush_dep_parent, parent_entry->flush_dep_height, (child_entry->flush_dep_height + 1)); + } /* end if */ + + /* Increase flush dependency height of parent entry */ + parent_entry->flush_dep_height = child_entry->flush_dep_height + 1; + } /* end if */ + + /* Set parent for child entry */ + child_entry->flush_dep_parent = parent_entry; + + + /* Post-conditions, for successful operation */ + HDassert(parent_entry->is_pinned); + HDassert(parent_entry->flush_dep_height > 0); + HDassert(parent_entry->flush_dep_height < H5C__NUM_FLUSH_DEP_HEIGHTS); + HDassert(prev_flush_dep_height <= parent_entry->flush_dep_height); + HDassert(parent_entry->child_flush_dep_height_rc[child_entry->flush_dep_height] > 0); + HDassert(NULL != child_entry->flush_dep_parent); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5C_create_flush_dependency() */ + + +/*------------------------------------------------------------------------- + * Function: H5C_destroy_flush_dependency() + * + * Purpose: Terminates a parent<-> child entry flush dependency. The + * parent entry must be pinned and have a positive flush + * dependency height (which could go to zero as a result of + * this operation). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * 3/05/09 + * + *------------------------------------------------------------------------- + */ +herr_t +H5C_destroy_flush_dependency(H5C_t * cache_ptr, void *parent_thing, + void * child_thing) +{ + H5C_cache_entry_t * parent_entry = (H5C_cache_entry_t *)parent_thing; /* Ptr to parent entry */ + H5C_cache_entry_t * child_entry = (H5C_cache_entry_t *)child_thing; /* Ptr to child entry */ +#ifndef NDEBUG + unsigned prev_flush_dep_height = parent_entry->flush_dep_height; /* Previous flush height for parent entry */ +#endif /* NDEBUG */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5C_destroy_flush_dependency, FAIL) + + /* Sanity checks */ + HDassert(cache_ptr); + HDassert(cache_ptr->magic == H5C__H5C_T_MAGIC); + HDassert(parent_entry); + HDassert(parent_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); + HDassert(H5F_addr_defined(parent_entry->addr)); + HDassert(parent_entry->flush_dep_height <= H5C__NUM_FLUSH_DEP_HEIGHTS); + HDassert(child_entry); + HDassert(child_entry->flush_dep_parent != child_entry); + HDassert(child_entry->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); + HDassert(H5F_addr_defined(child_entry->addr)); + + /* Usage checks */ + if(!parent_entry->is_pinned) + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry isn't pinned") + if(0 == parent_entry->flush_dep_height) + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry isn't a flush dependency parent") + if(NULL == child_entry->flush_dep_parent) + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Child entry doesn't have a flush dependency parent") + if(0 == parent_entry->child_flush_dep_height_rc[child_entry->flush_dep_height]) + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry flush dependency ref. count has no child entries of this height") + if(child_entry->flush_dep_parent != parent_entry) + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNDEPEND, FAIL, "Parent entry isn't flush dependency parent for child entry") + + /* Decrement the ref. count for flush dependency height of children for parent entry */ + parent_entry->child_flush_dep_height_rc[child_entry->flush_dep_height]--; + + /* Check for flush dependency ref. count at this height going to zero and + * parent entry flush dependency height dropping + */ + if(((child_entry->flush_dep_height + 1) == parent_entry->flush_dep_height) && + 0 == parent_entry->child_flush_dep_height_rc[child_entry->flush_dep_height]) { + int i; /* Local index variable */ + + /* Reverse scan for new flush dependency height of parent */ +#ifndef NDEBUG + for(i = (H5C__NUM_FLUSH_DEP_HEIGHTS - 1); i > (int)child_entry->flush_dep_height; i--) + HDassert(0 == parent_entry->child_flush_dep_height_rc[i]); +#endif /* NDEBUG */ + for(i = (int)child_entry->flush_dep_height; i >= 0; i--) + /* Check for child flush dependencies of this height */ + if(parent_entry->child_flush_dep_height_rc[i] > 0) + break; + + /* Sanity check */ + HDassert((unsigned)(i + 1) < parent_entry->flush_dep_height); + + /* Check if parent entry is a child in another flush dependency relationship */ + if(NULL != parent_entry->flush_dep_parent) { + /* Change flush dependency ref. counts of parent's parent */ + H5C_adjust_flush_dependency_rc(parent_entry->flush_dep_parent, parent_entry->flush_dep_height, (unsigned)(i + 1)); + } /* end if */ + + /* Increase flush dependency height of parent entry */ + parent_entry->flush_dep_height = (unsigned)(i + 1); + + /* Check for height of parent dropping to zero (i.e. no longer a + * parent of _any_ child flush dependencies). + */ + if(0 == parent_entry->flush_dep_height) { + if(!parent_entry->is_protected) + H5C__UPDATE_RP_FOR_UNPIN(cache_ptr, parent_entry, FAIL) + + /* Unpin parent entry */ + parent_entry->is_pinned = FALSE; + H5C__UPDATE_STATS_FOR_UNPIN(cache_ptr, parent_entry) + } /* end if */ + } /* end if */ + + /* Reset parent of child entry */ + child_entry->flush_dep_parent = NULL; + + /* Post-conditions, for successful operation */ + HDassert(prev_flush_dep_height >= parent_entry->flush_dep_height); + HDassert(NULL == child_entry->flush_dep_parent); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5C_destroy_flush_dependency() */ + + /*************************************************************************/ /**************************** Private Functions: *************************/ /*************************************************************************/ @@ -9874,8 +10216,6 @@ H5C_flush_invalidate_cache(H5F_t * f, herr_t ret_value = SUCCEED; hbool_t done = FALSE; hbool_t first_flush = TRUE; - hbool_t first_pass = TRUE; - hbool_t have_pinned_entries; int32_t protected_entries = 0; int32_t i; int32_t cur_pel_len; @@ -9952,347 +10292,376 @@ H5C_flush_invalidate_cache(H5F_t * f, while ( ! done ) { - first_pass = FALSE; + unsigned curr_flush_dep_height = 0; + unsigned flush_dep_passes = 0; - have_pinned_entries = ( cur_pel_len > 0 ); + /* Loop over all flush dependency heights of entries */ + while((curr_flush_dep_height <= H5C__NUM_FLUSH_DEP_HEIGHTS) && + (cache_ptr->index_len > 0 ) && + (flush_dep_passes < H5C__MAX_PASSES_ON_FLUSH) ) + { + hbool_t flushed_during_dep_loop = FALSE; - /* first, try to flush-destroy any dirty entries. Do this by - * making a scan through the slist. Note that new dirty entries - * may be created by the flush call backs. Thus it is possible - * that the slist will not be empty after we finish the scan. - */ + /* first, try to flush-destroy any dirty entries. Do this by + * making a scan through the slist. Note that new dirty entries + * may be created by the flush call backs. Thus it is possible + * that the slist will not be empty after we finish the scan. + */ - if ( cache_ptr->slist_len == 0 ) { + if ( cache_ptr->slist_len == 0 ) { - node_ptr = NULL; - HDassert( cache_ptr->slist_size == 0 ); + node_ptr = NULL; + HDassert( cache_ptr->slist_size == 0 ); - } else { + } else { - node_ptr = H5SL_first(cache_ptr->slist_ptr); + node_ptr = H5SL_first(cache_ptr->slist_ptr); - if ( node_ptr == NULL ) { - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "slist_len != 0 && node_ptr == NULL"); - } + if ( node_ptr == NULL ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "slist_len != 0 && node_ptr == NULL"); + } - next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); + next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); - if ( next_entry_ptr == NULL ) { - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "next_entry_ptr == NULL 1 ?!?!"); - } -#ifndef NDEBUG - HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC ); -#endif /* NDEBUG */ - HDassert( next_entry_ptr->is_dirty ); - HDassert( next_entry_ptr->in_slist ); + if ( next_entry_ptr == NULL ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "next_entry_ptr == NULL 1 ?!?!"); + } + HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC ); + HDassert( next_entry_ptr->is_dirty ); + HDassert( next_entry_ptr->in_slist ); - } + } #if H5C_DO_SANITY_CHECKS - /* Depending on circumstances, H5C_flush_single_entry() will - * remove dirty entries from the slist as it flushes them. - * Thus for sanity checks we must make note of the initial - * slist length and size before we do any flushes. - */ - initial_slist_len = cache_ptr->slist_len; - initial_slist_size = cache_ptr->slist_size; - - /* There is also the possibility that entries will be - * dirtied, resized, and/or renamed as the result of - * calls to the flush callbacks. We use the slist_len_increase - * and slist_size_increase increase fields in struct H5C_t - * to track these changes for purpose of sanity checking. - * To this end, we must zero these fields before we start - * the pass through the slist. - */ - cache_ptr->slist_len_increase = 0; - cache_ptr->slist_size_increase = 0; + /* Depending on circumstances, H5C_flush_single_entry() will + * remove dirty entries from the slist as it flushes them. + * Thus for sanity checks we must make note of the initial + * slist length and size before we do any flushes. + */ + initial_slist_len = cache_ptr->slist_len; + initial_slist_size = cache_ptr->slist_size; - /* Finally, reset the actual_slist_len and actual_slist_size - * fields to zero, as these fields are used to accumulate - * the slist lenght and size that we see as we scan through - * the slist. - */ - actual_slist_len = 0; - actual_slist_size = 0; -#endif /* H5C_DO_SANITY_CHECKS */ + /* There is also the possibility that entries will be + * dirtied, resized, and/or renamed as the result of + * calls to the flush callbacks. We use the slist_len_increase + * and slist_size_increase increase fields in struct H5C_t + * to track these changes for purpose of sanity checking. + * To this end, we must zero these fields before we start + * the pass through the slist. + */ + cache_ptr->slist_len_increase = 0; + cache_ptr->slist_size_increase = 0; - while ( node_ptr != NULL ) - { - entry_ptr = next_entry_ptr; - - /* With the advent of the fractal heap, it is possible - * that the flush callback will dirty and/or resize - * other entries in the cache. In particular, while - * Quincey has promised me that this will never happen, - * it is possible that the flush callback for an - * entry may protect an entry that is not in the cache, - * perhaps causing the cache to flush and possibly - * evict the entry associated with node_ptr to make - * space for the new entry. - * - * Thus we do a bit of extra sanity checking on entry_ptr, - * and break out of this scan of the skip list if we - * detect major problems. We have a bit of leaway on the - * number of passes though the skip list, so this shouldn't - * be an issue in the flush in and of itself, as it should - * be all but impossible for this to happen more than once - * in any flush. - * - * Observe that that breaking out of the scan early - * shouldn't break the sanity checks just after the end - * of this while loop. - * - * If an entry has merely been marked clean and removed from - * the s-list, we simply break out of the scan. - * - * If the entry has been evicted, we flag an error and - * exit. + /* Finally, reset the actual_slist_len and actual_slist_size + * fields to zero, as these fields are used to accumulate + * the slist lenght and size that we see as we scan through + * the slist. */ + actual_slist_len = 0; + actual_slist_size = 0; +#endif /* H5C_DO_SANITY_CHECKS */ + + while ( node_ptr != NULL ) + { + entry_ptr = next_entry_ptr; + + /* With the advent of the fractal heap, it is possible + * that the flush callback will dirty and/or resize + * other entries in the cache. In particular, while + * Quincey has promised me that this will never happen, + * it is possible that the flush callback for an + * entry may protect an entry that is not in the cache, + * perhaps causing the cache to flush and possibly + * evict the entry associated with node_ptr to make + * space for the new entry. + * + * Thus we do a bit of extra sanity checking on entry_ptr, + * and break out of this scan of the skip list if we + * detect major problems. We have a bit of leaway on the + * number of passes though the skip list, so this shouldn't + * be an issue in the flush in and of itself, as it should + * be all but impossible for this to happen more than once + * in any flush. + * + * Observe that that breaking out of the scan early + * shouldn't break the sanity checks just after the end + * of this while loop. + * + * If an entry has merely been marked clean and removed from + * the s-list, we simply break out of the scan. + * + * If the entry has been evicted, we flag an error and + * exit. + */ #ifndef NDEBUG - if ( entry_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) { + if ( entry_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) { - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "entry_ptr->magic is invalid ?!?!"); + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "entry_ptr->magic is invalid ?!?!"); - } else + } else #endif /* NDEBUG */ - if ( ( ! entry_ptr->is_dirty ) || - ( ! entry_ptr->in_slist ) ) { + if ( ( ! entry_ptr->is_dirty ) || + ( ! entry_ptr->in_slist ) ) { - /* the s-list has been modified out from under us. - * break out of the loop. - */ - break; - } + /* the s-list has been modified out from under us. + * break out of the loop. + */ + goto end_of_inner_loop;; + } - /* increment node pointer now, before we delete its target - * from the slist. - */ + /* increment node pointer now, before we delete its target + * from the slist. + */ - node_ptr = H5SL_next(node_ptr); - if ( node_ptr != NULL ) { + node_ptr = H5SL_next(node_ptr); + if ( node_ptr != NULL ) { - next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); + next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr); - if ( next_entry_ptr == NULL ) { - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "next_entry_ptr == NULL 2 ?!?!"); - } -#ifndef NDEBUG - HDassert( next_entry_ptr->magic == - H5C__H5C_CACHE_ENTRY_T_MAGIC ); -#endif /* NDEBUG */ - HDassert( next_entry_ptr->is_dirty ); - HDassert( next_entry_ptr->in_slist ); + if ( next_entry_ptr == NULL ) { + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "next_entry_ptr == NULL 2 ?!?!"); + } + HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC ); + HDassert( next_entry_ptr->is_dirty ); + HDassert( next_entry_ptr->in_slist ); - } else { + } else { - next_entry_ptr = NULL; - } + next_entry_ptr = NULL; + } - /* Note that we now remove nodes from the slist as we flush - * the associated entries, instead of leaving them there - * until we are done, and then destroying all nodes in - * the slist. - * - * While this optimization used to be easy, with the possibility - * of new entries being added to the slist in the midst of the - * flush, we must keep the slist in cannonical form at all - * times. - */ + /* Note that we now remove nodes from the slist as we flush + * the associated entries, instead of leaving them there + * until we are done, and then destroying all nodes in + * the slist. + * + * While this optimization used to be easy, with the possibility + * of new entries being added to the slist in the midst of the + * flush, we must keep the slist in cannonical form at all + * times. + */ - HDassert( entry_ptr != NULL ); - HDassert( entry_ptr->in_slist ); + HDassert( entry_ptr != NULL ); + HDassert( entry_ptr->in_slist ); #if H5C_DO_SANITY_CHECKS - /* update actual_slist_len & actual_slist_size before - * the flush. Note that the entry will be removed - * from the slist after the flush, and thus may be - * resized by the flush callback. This is OK, as - * we will catch the size delta in - * cache_ptr->slist_size_increase. - * - * Note that we include pinned entries in this count, even - * though we will not actually flush them. - */ - actual_slist_len++; - actual_slist_size += entry_ptr->size; + /* update actual_slist_len & actual_slist_size before + * the flush. Note that the entry will be removed + * from the slist after the flush, and thus may be + * resized by the flush callback. This is OK, as + * we will catch the size delta in + * cache_ptr->slist_size_increase. + * + * Note that we include pinned entries in this count, even + * though we will not actually flush them. + */ + actual_slist_len++; + actual_slist_size += entry_ptr->size; #endif /* H5C_DO_SANITY_CHECKS */ - if ( entry_ptr->is_protected ) { - - /* we have major problems -- but lets flush - * everything we can before we flag an error. - */ - protected_entries++; + if ( entry_ptr->is_protected ) { - } else if ( entry_ptr->is_pinned ) { + /* we have major problems -- but lets flush + * everything we can before we flag an error. + */ + protected_entries++; - /* Test to see if we are can flush the entry now. - * If we can, go ahead and flush, but don't tell - * H5C_flush_single_entry() to destroy the entry - * as pinned entries can't be evicted. - */ - if ( TRUE ) { /* When we get to multithreaded cache, - * we will need either locking code, and/or - * a test to see if the entry is in flushable - * condition here. - */ + } else if ( entry_ptr->is_pinned ) { - status = H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - cache_ptr, - NULL, - entry_ptr->addr, - H5C__NO_FLAGS_SET, - &first_flush, - FALSE); - if ( status < 0 ) { + /* Test to see if we are can flush the entry now. + * If we can, go ahead and flush, but don't tell + * H5C_flush_single_entry() to destroy the entry + * as pinned entries can't be evicted. + */ + if(entry_ptr->flush_dep_height == curr_flush_dep_height ) { + status = H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + cache_ptr, + NULL, + entry_ptr->addr, + H5C__NO_FLAGS_SET, + &first_flush, + FALSE); + if ( status < 0 ) { - /* This shouldn't happen -- if it does, we are toast - * so just scream and die. - */ + /* This shouldn't happen -- if it does, we are toast + * so just scream and die. + */ - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "dirty pinned entry flush failed.") - } - } - } else { + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "dirty pinned entry flush failed.") + } /* end if */ + flushed_during_dep_loop = TRUE; + } /* end if */ + else if(entry_ptr->flush_dep_height < curr_flush_dep_height) + /* This shouldn't happen -- if it does, just scream and die. */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry below current flush dep. height.") + } /* end if */ + else { + if(entry_ptr->flush_dep_height == curr_flush_dep_height ){ - status = H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - cache_ptr, - NULL, - entry_ptr->addr, - (cooked_flags | - H5C__FLUSH_INVALIDATE_FLAG), - &first_flush, - TRUE); - if ( status < 0 ) { + status = H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + cache_ptr, + NULL, + entry_ptr->addr, + (cooked_flags | + H5C__FLUSH_INVALIDATE_FLAG), + &first_flush, + TRUE); + if ( status < 0 ) { - /* This shouldn't happen -- if it does, we are toast so - * just scream and die. - */ + /* This shouldn't happen -- if it does, we are toast so + * just scream and die. + */ - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "dirty entry flush destroy failed.") - } - } - } /* end while loop scanning skip list */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "dirty entry flush destroy failed.") + } /* end if */ + flushed_during_dep_loop = TRUE; + } /* end if */ + else if(entry_ptr->flush_dep_height < curr_flush_dep_height) + /* This shouldn't happen -- if it does, just scream and die. */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry below current flush dep. height.") + } /* end else */ + } /* end while loop scanning skip list */ #if H5C_DO_SANITY_CHECKS - /* It is possible that entries were added to the slist during - * the scan, either before or after scan pointer. The following - * asserts take this into account. - * - * Don't bother with the sanity checks if node_ptr != NULL, as - * in this case we broke out of the loop because it got changed - * out from under us. - */ + /* It is possible that entries were added to the slist during + * the scan, either before or after scan pointer. The following + * asserts take this into account. + * + * Don't bother with the sanity checks if node_ptr != NULL, as + * in this case we broke out of the loop because it got changed + * out from under us. + */ - if ( node_ptr == NULL ) { + if ( node_ptr == NULL ) { - HDassert( (actual_slist_len + cache_ptr->slist_len) == - (initial_slist_len + cache_ptr->slist_len_increase) ); - HDassert( (actual_slist_size + cache_ptr->slist_size) == - (initial_slist_size + cache_ptr->slist_size_increase) ); - } + HDassert( (actual_slist_len + cache_ptr->slist_len) == + (initial_slist_len + cache_ptr->slist_len_increase) ); + HDassert( (actual_slist_size + cache_ptr->slist_size) == + (initial_slist_size + cache_ptr->slist_size_increase) ); + } #endif /* H5C_DO_SANITY_CHECKS */ - /* Since we are doing a destroy, we must make a pass through - * the hash table and try to flush - destroy all entries that - * remain. - * - * It used to be that all entries remaining in the cache at - * this point had to be clean, but with the fractal heap mods - * this may not be the case. If so, we will flush entries out - * of increasing address order. - * - * Writes to disk are possible here. - */ - for ( i = 0; i < H5C__HASH_TABLE_LEN; i++ ) - { - next_entry_ptr = cache_ptr->index[i]; - - while ( next_entry_ptr != NULL ) + /* Since we are doing a destroy, we must make a pass through + * the hash table and try to flush - destroy all entries that + * remain. + * + * It used to be that all entries remaining in the cache at + * this point had to be clean, but with the fractal heap mods + * this may not be the case. If so, we will flush entries out + * of increasing address order. + * + * Writes to disk are possible here. + */ + for ( i = 0; i < H5C__HASH_TABLE_LEN; i++ ) { - entry_ptr = next_entry_ptr; + next_entry_ptr = cache_ptr->index[i]; - next_entry_ptr = entry_ptr->ht_next; -#ifndef NDEBUG - HDassert ( ( next_entry_ptr == NULL ) || - ( next_entry_ptr->magic == - H5C__H5C_CACHE_ENTRY_T_MAGIC ) ); -#endif /* NDEBUG */ - if ( entry_ptr->is_protected ) { + while ( next_entry_ptr != NULL ) + { + entry_ptr = next_entry_ptr; - /* we have major problems -- but lets flush and destroy - * everything we can before we flag an error. - */ - protected_entries++; + next_entry_ptr = entry_ptr->ht_next; + HDassert ( ( next_entry_ptr == NULL ) || + ( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC ) ); + if ( entry_ptr->is_protected ) { - if ( ! entry_ptr->in_slist ) { + /* we have major problems -- but lets flush and destroy + * everything we can before we flag an error. + */ + protected_entries++; - HDassert( !(entry_ptr->is_dirty) ); - } - } else if ( ! ( entry_ptr->is_pinned ) ) { + if ( ! entry_ptr->in_slist ) { - status = H5C_flush_single_entry(f, - primary_dxpl_id, - secondary_dxpl_id, - cache_ptr, - NULL, - entry_ptr->addr, - (cooked_flags | - H5C__FLUSH_INVALIDATE_FLAG), - &first_flush, - TRUE); - if ( status < 0 ) { + HDassert( !(entry_ptr->is_dirty) ); + } + } else if ( ! ( entry_ptr->is_pinned ) ) { - /* This shouldn't happen -- if it does, we are toast so - * just scream and die. + /* Test to see if we are can flush the entry now. + * If we can, go ahead and flush. */ + if(entry_ptr->flush_dep_height == curr_flush_dep_height ){ + status = H5C_flush_single_entry(f, + primary_dxpl_id, + secondary_dxpl_id, + cache_ptr, + NULL, + entry_ptr->addr, + (cooked_flags | + H5C__FLUSH_INVALIDATE_FLAG), + &first_flush, + TRUE); + if ( status < 0 ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ - "Entry flush destroy failed.") - } - } - /* We can't do anything if the entry is pinned. The - * hope is that the entry will be unpinned as the - * result of destroys of entries that reference it. - * - * We detect this by noting the change in the number - * of pinned entries from pass to pass. If it stops - * shrinking before it hits zero, we scream and die. - */ - /* if the flush function on the entry we last evicted - * loaded an entry into cache (as Quincey has promised me - * it never will), and if the cache was full, it is - * possible that *next_entry_ptr was flushed or evicted. - * - * Test to see if this happened here. Note that if this - * test is triggred, we are accessing a deallocated piece - * of dynamically allocated memory, so we just scream and - * die. - */ -#ifndef NDEBUG - if ( ( next_entry_ptr != NULL ) && - ( next_entry_ptr->magic != - H5C__H5C_CACHE_ENTRY_T_MAGIC ) ) { + /* This shouldn't happen -- if it does, we are toast so + * just scream and die. + */ - /* Something horrible has happened to - * *next_entry_ptr -- scream and die. + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \ + "Entry flush destroy failed.") + } + flushed_during_dep_loop = TRUE; + } /* end if */ + else if(entry_ptr->flush_dep_height < curr_flush_dep_height) + /* This shouldn't happen -- if it does, just scream and die. */ + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "dirty entry below current flush dep. height.") + } /* end if */ + /* We can't do anything if the entry is pinned. The + * hope is that the entry will be unpinned as the + * result of destroys of entries that reference it. + * + * We detect this by noting the change in the number + * of pinned entries from pass to pass. If it stops + * shrinking before it hits zero, we scream and die. */ - HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ - "next_entry_ptr->magic is invalid?!?!?.") - } + /* if the flush function on the entry we last evicted + * loaded an entry into cache (as Quincey has promised me + * it never will), and if the cache was full, it is + * possible that *next_entry_ptr was flushed or evicted. + * + * Test to see if this happened here. Note that if this + * test is triggred, we are accessing a deallocated piece + * of dynamically allocated memory, so we just scream and + * die. + */ +#ifndef NDEBUG + if ( ( next_entry_ptr != NULL ) && + ( next_entry_ptr->magic != + H5C__H5C_CACHE_ENTRY_T_MAGIC ) ) { + + /* Something horrible has happened to + * *next_entry_ptr -- scream and die. + */ + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ + "next_entry_ptr->magic is invalid?!?!?.") + } #endif /* NDEBUG */ - } /* end while loop scanning hash table bin */ - } /* end for loop scanning hash table */ + } /* end while loop scanning hash table bin */ + } /* end for loop scanning hash table */ + + /* Check for incrementing flush dependency height */ + if(flushed_during_dep_loop) { + /* If we flushed an entry at this flush dependency height + * start over at the bottom level of the flush dependencies + */ + curr_flush_dep_height = 0; + + /* Make certain we don't get stuck in an infinite loop */ + flush_dep_passes++; + } /* end if */ + else + curr_flush_dep_height++; + + } /* end while loop over flush dependency heights */ +end_of_inner_loop: old_pel_len = cur_pel_len; cur_pel_len = cache_ptr->pel_len; @@ -11029,8 +11398,9 @@ H5C_load_entry(H5F_t * f, #endif /* NDEBUG */ { void * thing = NULL; - void * ret_value = NULL; H5C_cache_entry_t * entry_ptr = NULL; + unsigned u; /* Local index variable */ + void * ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5C_load_entry) @@ -11097,6 +11467,12 @@ H5C_load_entry(H5F_t * f, HDassert( entry_ptr->size < H5C_MAX_ENTRY_SIZE ); + /* Initialize flush dependency height fields */ + entry_ptr->flush_dep_parent = NULL; + for(u = 0; u < H5C__NUM_FLUSH_DEP_HEIGHTS; u++) + entry_ptr->child_flush_dep_height_rc[u] = 0; + entry_ptr->flush_dep_height = 0; + entry_ptr->ht_next = NULL; entry_ptr->ht_prev = NULL; diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 4ce321c..855c861 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -32,7 +32,7 @@ #include "H5Cpublic.h" /*public prototypes */ -/* Pivate headers needed by this header */ +/* Private headers needed by this header */ #include "H5private.h" /* Generic Functions */ #include "H5Fprivate.h" /* File access */ @@ -183,6 +183,14 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr, #define H5C__DEFAULT_MAX_CACHE_SIZE ((size_t)(4 * 1024 * 1024)) #define H5C__DEFAULT_MIN_CLEAN_SIZE ((size_t)(2 * 1024 * 1024)) +/* Maximum height of flush dependency relationships between entries. This is + * currently tuned to the extensible array (H5EA) data structure, which only + * requires 4 levels of dependency (i.e. heights 0-4). + */ + +#define H5C__NUM_FLUSH_DEP_HEIGHTS 4 + + /**************************************************************************** * @@ -496,6 +504,12 @@ typedef struct H5C_cache_entry_t hbool_t destroy_in_progress; hbool_t free_file_space_on_destroy; + /* fields supporting the 'flush dependency height': */ + + struct H5C_cache_entry_t * flush_dep_parent; + uint64_t child_flush_dep_height_rc[H5C__NUM_FLUSH_DEP_HEIGHTS]; + unsigned flush_dep_height; + /* fields supporting the hash table: */ struct H5C_cache_entry_t * ht_next; @@ -1040,6 +1054,9 @@ H5_DLL herr_t H5C_rename_entry(H5C_t * cache_ptr, H5_DLL herr_t H5C_pin_protected_entry(H5C_t * cache_ptr, void * thing); +H5_DLL herr_t H5C_create_flush_dependency(H5C_t *cache_ptr, void *parent_thing, + void *child_thing); + H5_DLL void * H5C_protect(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, @@ -1079,6 +1096,9 @@ H5_DLL void H5C_stats__reset(H5C_t * cache_ptr); H5_DLL herr_t H5C_unpin_entry(H5C_t * cache_ptr, void * thing); +H5_DLL herr_t H5C_destroy_flush_dependency(H5C_t *cache_ptr, void *parent_thing, + void *child_thing); + H5_DLL herr_t H5C_unprotect(H5F_t * f, hid_t primary_dxpl_id, hid_t secondary_dxpl_id, @@ -368,14 +368,13 @@ done: herr_t H5Dclose(hid_t dset_id) { - H5D_t *dset; /* Dataset object to release */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Dclose, FAIL) H5TRACE1("e", "i", dset_id); /* Check args */ - if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) + if(NULL == H5I_object_verify(dset_id, H5I_DATASET)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") /* diff --git a/src/H5Dio.c b/src/H5Dio.c index c1d57fd..cc75981 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -66,8 +66,7 @@ static herr_t H5D_typeinfo_init(const H5D_t *dset, const H5D_dxpl_cache_t *dxpl_ H5D_type_info_t *type_info); #ifdef H5_HAVE_PARALLEL static herr_t H5D_ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset, - const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id, - const H5S_t *file_space, const H5S_t *mem_space, + hid_t dxpl_id, const H5S_t *file_space, const H5S_t *mem_space, const H5D_type_info_t *type_info, const H5D_chunk_map_t *fm); static herr_t H5D_ioinfo_term(H5D_io_info_t *io_info); #endif /* H5_HAVE_PARALLEL */ @@ -396,7 +395,7 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, #ifdef H5_HAVE_PARALLEL /* Adjust I/O info for any parallel I/O */ - if(H5D_ioinfo_adjust(&io_info, dataset, dxpl_cache, dxpl_id, file_space, mem_space, &type_info, &fm) < 0) + if(H5D_ioinfo_adjust(&io_info, dataset, dxpl_id, file_space, mem_space, &type_info, &fm) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O") #endif /*H5_HAVE_PARALLEL*/ @@ -570,7 +569,7 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, #ifdef H5_HAVE_PARALLEL /* Adjust I/O info for any parallel I/O */ - if(H5D_ioinfo_adjust(&io_info, dataset, dxpl_cache, dxpl_id, file_space, mem_space, &type_info, &fm) < 0) + if(H5D_ioinfo_adjust(&io_info, dataset, dxpl_id, file_space, mem_space, &type_info, &fm) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O") #endif /*H5_HAVE_PARALLEL*/ @@ -845,8 +844,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5D_ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset, - const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id, +H5D_ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset, hid_t dxpl_id, const H5S_t *file_space, const H5S_t *mem_space, const H5D_type_info_t *type_info, const H5D_chunk_map_t *fm) { diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c index e4dd8b5..6693348 100644 --- a/src/H5Dmpio.c +++ b/src/H5Dmpio.c @@ -117,8 +117,10 @@ static herr_t H5D_inter_collective_io(H5D_io_info_t *io_info, static herr_t H5D_final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, size_t nelmts, MPI_Datatype *mpi_file_type, MPI_Datatype *mpi_buf_type); +#ifdef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS static herr_t H5D_sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm, H5D_chunk_addr_info_t chunk_addr_info_array[], int many_chunk_opt); +#endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */ static herr_t H5D_obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, H5P_genplist_t *dx_plist, uint8_t assign_io_mode[], haddr_t chunk_addr[]); static herr_t H5D_ioinfo_xfer_mode(H5D_io_info_t *io_info, H5P_genplist_t *dx_plist, @@ -1074,7 +1076,6 @@ static herr_t H5D_multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm, H5P_genplist_t *dx_plist) { - H5D_t *dataset = io_info->dset;/* Local pointer to dataset info */ H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ H5D_io_info_t cpt_io_info; /* Compact I/O info object */ @@ -1347,7 +1348,6 @@ static herr_t H5D_multi_chunk_collective_io_no_opt(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm, H5P_genplist_t *dx_plist) { - H5D_t *dataset = io_info->dset;/* Local pointer to dataset info */ H5SL_node_t *chunk_node; /* Current node in chunk skip list */ H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */ @@ -1366,7 +1366,7 @@ if(H5DEBUG(D)) { int mpi_rank; mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file); - HDfprintf(H5DEBUG(D), "coming to multi_chunk_collective_io_no_opt\n"); + HDfprintf(H5DEBUG(D), "Rank %d: coming to multi_chunk_collective_io_no_opt\n", mpi_rank); } #endif @@ -1614,7 +1614,6 @@ static herr_t H5D_final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, size_t mpi_buf_count, MPI_Datatype *mpi_file_type, MPI_Datatype *mpi_buf_type) { - int mpi_code; /* MPI return code */ hbool_t plist_is_setup = FALSE; /* Whether the dxpl has been customized */ herr_t ret_value = SUCCEED; @@ -1626,13 +1625,11 @@ H5D_final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info plist_is_setup = TRUE; if(io_info->op_type == H5D_IO_OP_WRITE) { - if((io_info->io_ops.single_write)(io_info, type_info, - (hsize_t)mpi_buf_count, NULL, NULL) < 0) + if((io_info->io_ops.single_write)(io_info, type_info, (hsize_t)mpi_buf_count, NULL, NULL) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed") } /* end if */ else { - if((io_info->io_ops.single_read)(io_info, type_info, - (hsize_t)mpi_buf_count, NULL, NULL) < 0) + if((io_info->io_ops.single_read)(io_info, type_info, (hsize_t)mpi_buf_count, NULL, NULL) < 0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed") } /* end else */ @@ -1649,6 +1646,7 @@ if(H5DEBUG(D)) FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_final_collective_io */ +#ifdef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS /*------------------------------------------------------------------------- * Function: H5D_sort_chunk @@ -1790,6 +1788,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_sort_chunk() */ +#endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */ /*------------------------------------------------------------------------- @@ -1833,17 +1832,19 @@ H5D_obtain_mpio_mode(H5D_io_info_t* io_info, H5D_chunk_map_t *fm, H5P_genplist_t *dx_plist, uint8_t assign_io_mode[], haddr_t chunk_addr[]) { int total_chunks; - unsigned percent_nproc_per_chunk,threshold_nproc_per_chunk; + unsigned percent_nproc_per_chunk, threshold_nproc_per_chunk; +#if defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) && defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS) H5FD_mpio_chunk_opt_t chunk_opt_mode; - uint8_t* io_mode_info=NULL; - uint8_t* recv_io_mode_info=NULL; - uint8_t* mergebuf=NULL; +#endif + uint8_t* io_mode_info = NULL; + uint8_t* recv_io_mode_info = NULL; + uint8_t* mergebuf = NULL; uint8_t* tempbuf; H5SL_node_t* chunk_node; H5D_chunk_info_t* chunk_info; - int mpi_size,mpi_rank; + int mpi_size, mpi_rank; MPI_Comm comm; - int ic,root; + int ic, root; int mpi_code; int mem_cleanup = 0; #ifdef H5_HAVE_INSTRUMENTED_LIBRARY diff --git a/src/H5Edefin.h b/src/H5Edefin.h index 612fcb1..b31b31b 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -164,6 +164,8 @@ hid_t H5E_CANTMARKDIRTY_g = FAIL; /* Unable to mark a pinned entry as dirt hid_t H5E_CANTDIRTY_g = FAIL; /* Unable to mark metadata as dirty */ hid_t H5E_CANTEXPUNGE_g = FAIL; /* Unable to expunge a metadata cache entry */ hid_t H5E_CANTRESIZE_g = FAIL; /* Unable to resize a metadata cache entry */ +hid_t H5E_CANTDEPEND_g = FAIL; /* Unable to create a flush dependency */ +hid_t H5E_CANTUNDEPEND_g = FAIL; /* Unable to destroy a flush dependency */ /* Link related errors */ hid_t H5E_TRAVERSE_g = FAIL; /* Link traversal failure */ diff --git a/src/H5Einit.h b/src/H5Einit.h index 20e156c..204644f 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -622,6 +622,16 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to resize a metadata cache entr HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") if((H5E_CANTRESIZE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_CANTDEPEND_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to create a flush dependency"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_CANTDEPEND_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_CANTUNDEPEND_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to destroy a flush dependency"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_CANTUNDEPEND_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") /* Link related errors */ assert(H5E_TRAVERSE_g==(-1)); diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index 4e981dc..736349a 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -266,6 +266,8 @@ H5_DLLVAR hid_t H5E_NOIDS_g; /* Out of IDs for group */ #define H5E_CANTDIRTY (H5OPEN H5E_CANTDIRTY_g) #define H5E_CANTEXPUNGE (H5OPEN H5E_CANTEXPUNGE_g) #define H5E_CANTRESIZE (H5OPEN H5E_CANTRESIZE_g) +#define H5E_CANTDEPEND (H5OPEN H5E_CANTDEPEND_g) +#define H5E_CANTUNDEPEND (H5OPEN H5E_CANTUNDEPEND_g) H5_DLLVAR hid_t H5E_CANTFLUSH_g; /* Unable to flush data from cache */ H5_DLLVAR hid_t H5E_CANTSERIALIZE_g; /* Unable to serialize data from cache */ H5_DLLVAR hid_t H5E_CANTLOAD_g; /* Unable to load metadata into cache */ @@ -282,6 +284,8 @@ H5_DLLVAR hid_t H5E_CANTMARKDIRTY_g; /* Unable to mark a pinned entry as dirty * H5_DLLVAR hid_t H5E_CANTDIRTY_g; /* Unable to mark metadata as dirty */ H5_DLLVAR hid_t H5E_CANTEXPUNGE_g; /* Unable to expunge a metadata cache entry */ H5_DLLVAR hid_t H5E_CANTRESIZE_g; /* Unable to resize a metadata cache entry */ +H5_DLLVAR hid_t H5E_CANTDEPEND_g; /* Unable to create a flush dependency */ +H5_DLLVAR hid_t H5E_CANTUNDEPEND_g; /* Unable to destroy a flush dependency */ /* Link related errors */ #define H5E_TRAVERSE (H5OPEN H5E_TRAVERSE_g) diff --git a/src/H5Eterm.h b/src/H5Eterm.h index 7595e7f..8936dc0 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -165,7 +165,9 @@ H5E_CANTUNPIN_g= H5E_CANTMARKDIRTY_g= H5E_CANTDIRTY_g= H5E_CANTEXPUNGE_g= -H5E_CANTRESIZE_g= +H5E_CANTRESIZE_g= +H5E_CANTDEPEND_g= +H5E_CANTUNDEPEND_g= /* Link related errors */ H5E_TRAVERSE_g= @@ -1115,6 +1115,9 @@ H5F_dest(H5F_t *f, hid_t dxpl_id) f->shared->mtab.child = (H5F_mount_t *)H5MM_xfree(f->shared->mtab.child); f->shared->mtab.nalloc = 0; + /* Free root group symbol table entry, if any */ + f->shared->root_ent = H5MM_xfree(f->shared->root_ent); + /* Destroy shared file struct */ f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared); diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c index 61eb318..fff31f3 100644 --- a/src/H5FDdirect.c +++ b/src/H5FDdirect.c @@ -1081,7 +1081,8 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h hbool_t _must_align = TRUE; herr_t ret_value=SUCCEED; /* Return value */ size_t alloc_size; - void *copy_buf, *p1, *p3; + void *copy_buf, *p1; + const void *p3; size_t _boundary; size_t _fbsize; size_t _cbsize; @@ -1187,7 +1188,7 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h HDmemcpy(p1, p3, copy_size); }else if(size >= _cbsize && copy_size > (alloc_size-(size_t)(copy_addr%_fbsize))) { HDmemcpy(p1, p3, (alloc_size - (size_t)(copy_addr % _fbsize))); - p3 = (unsigned char*)p3 + (alloc_size - (size_t)(copy_addr % _fbsize)); + p3 = (const unsigned char *)p3 + (alloc_size - (size_t)(copy_addr % _fbsize)); } /*look for the aligned position for writing the data*/ diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index 57da069..5e5349d 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -1913,7 +1913,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FD_mpio_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing) +H5FD_mpio_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing) { H5FD_mpio_t *file = (H5FD_mpio_t*)_file; herr_t ret_value = SUCCEED; diff --git a/src/H5FDmpiposix.c b/src/H5FDmpiposix.c index 245fc3e..ff5b118 100644 --- a/src/H5FDmpiposix.c +++ b/src/H5FDmpiposix.c @@ -1215,7 +1215,9 @@ H5FD_mpiposix_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size, const void *buf) { H5FD_mpiposix_t *file = (H5FD_mpiposix_t*)_file; +#if 0 /* JRM */ int mpi_code; /* MPI return code */ +#endif /* JRM */ ssize_t nbytes; /* Number of bytes written each I/O call */ H5P_genplist_t *plist; /* Property list pointer */ herr_t ret_value=SUCCEED; /* Return value */ diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c index 59e5b1e..0ae09a6 100644 --- a/src/H5FDstdio.c +++ b/src/H5FDstdio.c @@ -563,7 +563,9 @@ H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxp { H5FD_stdio_t *file = (H5FD_stdio_t*)_file; haddr_t addr; +#ifndef H5_HAVE_FSEEKO static const char *func = "H5FD_stdio_alloc"; /* Function Name for error reporting */ +#endif haddr_t ret_value; /* Return value */ /* Shut compiler up */ diff --git a/src/H5FDwindows.c b/src/H5FDwindows.c index ef26fec..37228d7 100644 --- a/src/H5FDwindows.c +++ b/src/H5FDwindows.c @@ -1008,7 +1008,7 @@ done: */ /* ARGSUSED */ static herr_t -H5FD_windows_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing) +H5FD_windows_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing) { H5FD_windows_t *file = (H5FD_windows_t*)_file; #ifndef WINDOWS_USE_STDIO diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h index 446c852..a799dc4 100644 --- a/src/H5FLprivate.h +++ b/src/H5FLprivate.h @@ -118,7 +118,7 @@ typedef struct H5FL_reg_head_t { #define H5FL_DEFINE(t) H5_DLL H5FL_DEFINE_COMMON(t) /* Reference a free list for type 't' defined in another file */ -#define H5FL_EXTERN(t) extern H5_DLL H5FL_reg_head_t H5FL_REG_NAME(t) +#define H5FL_EXTERN(t) H5_DLLVAR H5FL_reg_head_t H5FL_REG_NAME(t) /* Declare a static free list to manage objects of type 't' */ #define H5FL_DEFINE_STATIC(t) static H5FL_DEFINE_COMMON(t) @@ -142,7 +142,7 @@ typedef struct H5FL_reg_head_t { #define H5FL_DEFINE_COMMON(t) int UNUSED H5FL_REG_NAME(t) #define H5FL_DEFINE(t) H5_DLL H5FL_DEFINE_COMMON(t) -#define H5FL_EXTERN(t) extern H5_DLL H5FL_DEFINE_COMMON(t) +#define H5FL_EXTERN(t) H5_DLLVAR H5FL_DEFINE_COMMON(t) #define H5FL_DEFINE_STATIC(t) static H5FL_DEFINE_COMMON(t) #define H5FL_MALLOC(t) (t *)H5MM_malloc(sizeof(t)) #define H5FL_CALLOC(t) (t *)H5MM_calloc(sizeof(t)) @@ -187,7 +187,7 @@ typedef struct H5FL_blk_head_t { #define H5FL_BLK_DEFINE(t) H5_DLL H5FL_BLK_DEFINE_COMMON(t) /* Reference a free list for type 't' defined in another file */ -#define H5FL_BLK_EXTERN(t) extern H5_DLL H5FL_blk_head_t H5FL_BLK_NAME(t) +#define H5FL_BLK_EXTERN(t) H5_DLLVAR H5FL_blk_head_t H5FL_BLK_NAME(t) /* Declare a static free list to manage objects of type 't' */ #define H5FL_BLK_DEFINE_STATIC(t) static H5FL_BLK_DEFINE_COMMON(t) @@ -212,7 +212,7 @@ typedef struct H5FL_blk_head_t { #define H5FL_BLK_DEFINE_COMMON(t) int UNUSED H5FL_BLK_NAME(t) #define H5FL_BLK_DEFINE(t) H5_DLL H5FL_BLK_DEFINE_COMMON(t) -#define H5FL_BLK_EXTERN(t) extern H5_DLL H5FL_BLK_DEFINE_COMMON(t) +#define H5FL_BLK_EXTERN(t) H5_DLLVAR H5FL_BLK_DEFINE_COMMON(t) #define H5FL_BLK_DEFINE_STATIC(t) static H5FL_BLK_DEFINE_COMMON(t) #define H5FL_BLK_MALLOC(t,size) (uint8_t *)H5MM_malloc(size) #define H5FL_BLK_CALLOC(t,size) (uint8_t *)H5MM_calloc(size) @@ -263,7 +263,7 @@ typedef struct H5FL_arr_head_t { #define H5FL_BARR_DEFINE(b,t,m) H5_DLL H5FL_ARR_DEFINE_COMMON(sizeof(b),t,m) /* Reference a free list for arrays of type 't' defined in another file */ -#define H5FL_ARR_EXTERN(t) extern H5_DLL H5FL_arr_head_t H5FL_ARR_NAME(t) +#define H5FL_ARR_EXTERN(t) H5_DLLVAR H5FL_arr_head_t H5FL_ARR_NAME(t) /* Declare a static free list to manage arrays of type 't' */ #define H5FL_ARR_DEFINE_STATIC(t,m) static H5FL_ARR_DEFINE_COMMON(0,t,m) @@ -289,7 +289,7 @@ typedef struct H5FL_arr_head_t { #define H5FL_ARR_DEFINE(t,m) H5_DLL H5FL_ARR_DEFINE_COMMON(t,m) = 0 #define H5FL_BARR_DEFINE(b,t,m) H5_DLL H5FL_ARR_DEFINE_COMMON(t,m) = sizeof(b) -#define H5FL_ARR_EXTERN(t) extern H5_DLL H5FL_ARR_DEFINE_COMMON(t,m) +#define H5FL_ARR_EXTERN(t) H5_DLLVAR H5FL_ARR_DEFINE_COMMON(t,m) #define H5FL_ARR_DEFINE_STATIC(t,m) static H5FL_ARR_DEFINE_COMMON(t,m) = 0 #define H5FL_BARR_DEFINE_STATIC(b,t,m) static H5FL_ARR_DEFINE_COMMON(t,m) = sizeof(b) #define H5FL_ARR_MALLOC(t,elem) H5MM_malloc(H5FL_ARR_NAME(t) + ((elem)*sizeof(t))) @@ -319,7 +319,7 @@ typedef struct H5FL_seq_head_t { #define H5FL_SEQ_DEFINE(t) H5_DLL H5FL_SEQ_DEFINE_COMMON(t) /* Reference a free list for sequences of type 't' defined in another file */ -#define H5FL_SEQ_EXTERN(t) extern H5_DLL H5FL_seq_head_t H5FL_SEQ_NAME(t) +#define H5FL_SEQ_EXTERN(t) H5_DLLVAR H5FL_seq_head_t H5FL_SEQ_NAME(t) /* Declare a static free list to manage sequences of type 't' */ #define H5FL_SEQ_DEFINE_STATIC(t) static H5FL_SEQ_DEFINE_COMMON(t) @@ -341,7 +341,7 @@ typedef struct H5FL_seq_head_t { #define H5FL_SEQ_DEFINE_COMMON(t) int UNUSED H5FL_SEQ_NAME(t) #define H5FL_SEQ_DEFINE(t) H5_DLL H5FL_SEQ_DEFINE_COMMON(t) -#define H5FL_SEQ_EXTERN(t) extern H5_DLL H5FL_SEQ_DEFINE_COMMON(t) +#define H5FL_SEQ_EXTERN(t) H5_DLLVAR H5FL_SEQ_DEFINE_COMMON(t) #define H5FL_SEQ_DEFINE_STATIC(t) static H5FL_SEQ_DEFINE_COMMON(t) #define H5FL_SEQ_MALLOC(t,elem) (t *)H5MM_malloc((elem)*sizeof(t)) #define H5FL_SEQ_CALLOC(t,elem) (t *)H5MM_calloc((elem)*sizeof(t)) diff --git a/src/H5Fdbg.c b/src/H5Fdbg.c index e05c32a..a4577c9 100644 --- a/src/H5Fdbg.c +++ b/src/H5Fdbg.c @@ -123,21 +123,26 @@ H5F_debug(H5F_t *f, FILE *stream, int indent, int fwidth) "Root group symbol table entry:", f->shared->root_grp ? "" : "(none)"); if(f->shared->root_grp) { - H5O_loc_t *root_oloc; /* Root object location */ - H5G_entry_t root_ent; /* Constructed root symbol table entry */ - - /* Reset the root group entry */ - H5G_ent_reset(&root_ent); - - /* Build up a simulated root group symbol table entry */ - root_oloc = H5G_oloc(f->shared->root_grp); - HDassert(root_oloc); - root_ent.type = H5G_NOTHING_CACHED; - root_ent.header = root_oloc->addr; - root_ent.file = f; - - /* Display root group symbol table entry info */ - H5G_ent_debug(f, &root_ent, stream, indent + 3, MAX(0, fwidth - 3), NULL); + if(f->shared->root_ent) /* Use real root group symbol table entry */ + H5G_ent_debug(f, f->shared->root_ent, stream, indent + 3, + MAX(0, fwidth - 3), NULL); + else { + H5O_loc_t *root_oloc; /* Root object location */ + H5G_entry_t root_ent; /* Constructed root symbol table entry */ + + /* Reset the root group entry */ + H5G_ent_reset(&root_ent); + + /* Build up a simulated root group symbol table entry */ + root_oloc = H5G_oloc(f->shared->root_grp); + HDassert(root_oloc); + root_ent.type = H5G_NOTHING_CACHED; + root_ent.header = root_oloc->addr; + root_ent.file = f; + + /* Display root group symbol table entry info */ + H5G_ent_debug(f, &root_ent, stream, indent + 3, MAX(0, fwidth - 3), NULL); + } } /* end if */ done: diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index cc74a80..4080705 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -158,6 +158,7 @@ typedef struct H5F_file_t { int ncwfs; /* Num entries on cwfs list */ struct H5HG_heap_t **cwfs; /* Global heap cache */ struct H5G_t *root_grp; /* Open root group */ + H5G_entry_t *root_ent; /* Root group symbol table entry */ H5FO_t *open_objs; /* Open objects in file */ H5RC_t *grp_btree_shared; /* Ref-counted group B-tree node info */ @@ -193,7 +194,7 @@ struct H5F_t { H5FO_t *obj_count; /* # of time each object is opened through top file structure */ hid_t file_id; /* ID of this file */ hbool_t closing; /* File is in the process of being closed */ - struct H5F_t *parent; /* Parent file that this file is mounted to */ + struct H5F_t *parent; /* Parent file that this file is mounted to */ unsigned nmounts; /* Number of children mounted to this file */ }; diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index 3c914bd..70e0954 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -383,7 +383,8 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc) H5F_addr_decode(f, (const uint8_t **)&p, &shared->extension_addr/*out*/); H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/); H5F_addr_decode(f, (const uint8_t **)&p, &shared->driver_addr/*out*/); - if(H5G_obj_ent_decode(f, (const uint8_t **)&p, root_loc->oloc/*out*/) < 0) + if(H5G_obj_ent_decode(f, (const uint8_t **)&p, root_loc->oloc/*out*/, + &shared->root_ent/*out*/) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read root symbol entry") /* @@ -896,6 +896,24 @@ H5G_mkroot(H5F_t *f, hid_t dxpl_id, H5G_loc_t *loc) */ if(H5O_open(loc->oloc) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open root group") + +#ifndef H5_STRICT_FORMAT_CHECKS + /* If symbol table information is cached, check if we should replace the + * symbol table message with the cached symbol table information */ + if((H5F_INTENT(f) & H5F_ACC_RDWR) && f->shared->root_ent + && (f->shared->root_ent->type == H5G_CACHED_STAB)) { + H5O_stab_t cached_stab; + + /* Retrieve the cached symbol table information */ + cached_stab.btree_addr = f->shared->root_ent->cache.stab.btree_addr; + cached_stab.heap_addr = f->shared->root_ent->cache.stab.heap_addr; + + /* Check if the symbol table message is valid, and replace with the + * cached symbol table if necessary */ + if(H5G_stab_valid(loc->oloc, dxpl_id, &cached_stab) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to verify symbol table") + } /* end if */ +#endif /* H5_STRICT_FORMAT_CHECKS */ } /* end else */ /* Create the path names for the root group's entry */ diff --git a/src/H5Gdense.c b/src/H5Gdense.c index 6cc15b8..322b31b 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -988,9 +988,10 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, /* Check on iteration order */ if(order == H5_ITER_NATIVE) { - HDassert(H5F_addr_defined(bt2_addr)); H5G_bt2_ud_it_t udata; /* User data for iterator callback */ + HDassert(H5F_addr_defined(bt2_addr)); + /* Open the fractal heap */ if(NULL == (fheap = H5HF_open(f, dxpl_id, linfo->fheap_addr))) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") diff --git a/src/H5Gloc.c b/src/H5Gloc.c index 908c9a3..b6a3a17 100644 --- a/src/H5Gloc.c +++ b/src/H5Gloc.c @@ -727,6 +727,7 @@ H5G_loc_set_comment_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, { H5G_loc_sc_t *udata = (H5G_loc_sc_t *)_udata; /* User data passed in */ H5O_name_t comment; /* Object header "comment" message */ + htri_t exists; /* Whether a "comment" message already exists */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5G_loc_set_comment_cb) @@ -735,9 +736,14 @@ H5G_loc_set_comment_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, if(obj_loc == NULL) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist") + /* Check for existing comment message */ + if((exists = H5O_msg_exists(obj_loc->oloc, H5O_NAME_ID, udata->dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read object header") + /* Remove the previous comment message if any */ - if(H5O_msg_remove(obj_loc->oloc, H5O_NAME_ID, 0, TRUE, udata->dxpl_id) < 0) - H5E_clear_stack(NULL); + if(exists) + if(H5O_msg_remove(obj_loc->oloc, H5O_NAME_ID, 0, TRUE, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete existing comment object header message") /* Add the new message */ if(udata->comment && *udata->comment) { @@ -830,7 +836,7 @@ H5G_loc_get_comment_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, } else { if(udata->comment && udata->bufsize) HDstrncpy(udata->comment, comment.s, udata->bufsize); - udata->comment_size = HDstrlen(comment.s); + udata->comment_size = (ssize_t)HDstrlen(comment.s); H5O_msg_reset(H5O_NAME_ID, &comment); } /* end else */ diff --git a/src/H5Gname.c b/src/H5Gname.c index 205f2a2..581b649 100644 --- a/src/H5Gname.c +++ b/src/H5Gname.c @@ -578,7 +578,6 @@ H5G_name_move_path(H5RS_str_t **path_r_ptr, const char *full_suffix, const char if(full_suffix_len < path_len) { const char *dst_suffix; /* Destination suffix that changes */ const char *src_suffix; /* Source suffix that changes */ - const char *path_prefix; /* Prefix for path */ size_t path_prefix_len; /* Length of path prefix */ const char *path_prefix2; /* 2nd prefix for path */ size_t path_prefix2_len; /* Length of 2nd path prefix */ @@ -589,7 +588,6 @@ H5G_name_move_path(H5RS_str_t **path_r_ptr, const char *full_suffix, const char /* Compute path prefix before full suffix*/ - path_prefix = path; path_prefix_len = path_len - full_suffix_len; /* Determine the common prefix for src & dst paths */ diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 6b16544..fe381fd 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -815,7 +815,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, /* Get a pointer to the name of the link */ if(NULL == (lnk.name = (char *)H5HL_offset_into(f, udata->common.heap, sn->entry[idx].name_off))) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get link name") + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5B_INS_ERROR, "unable to get link name") /* Set up rest of link structure */ lnk.corder_valid = FALSE; @@ -833,7 +833,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, /* Replace any object names */ if(H5G_link_name_replace(f, dxpl_id, udata->grp_full_path_r, &lnk) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get object type") + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5B_INS_ERROR, "unable to get object type") /* Decrement the ref. count for hard links */ if(lnk.type == H5L_TYPE_HARD) { diff --git a/src/H5Gobj.c b/src/H5Gobj.c index 3220b67..2eb1924 100644 --- a/src/H5Gobj.c +++ b/src/H5Gobj.c @@ -237,31 +237,49 @@ done: *------------------------------------------------------------------------- */ herr_t -H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp, H5O_loc_t *oloc) +H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp, H5O_loc_t *oloc, H5G_entry_t **entp) { const uint8_t *p_ret = *pp; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5G_obj_ent_decode) + FUNC_ENTER_NOAPI(H5G_obj_ent_decode, FAIL) /* check arguments */ HDassert(f); HDassert(pp); HDassert(oloc); - /* Set file pointer for root object location */ - oloc->file = f; + if(entp) { + /* If entp is not NULL we allocate space for the symbol table entry and + * decode the entire entry. */ + if(!(*entp)) /* Only allocate space if *entp is NULL */ + if(NULL == (*entp = (H5G_entry_t *) H5MM_calloc(sizeof(H5G_entry_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate space for symbol table entry") + if(H5G_ent_decode_vec(f, pp, *entp, 1) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode symbol table entry") + + /* Set oloc to the correct values */ + oloc->file = (*entp)->file; + oloc->addr = (*entp)->header; + } else { + /* Set file pointer for root object location */ + oloc->file = f; + + /* decode header */ + *pp += H5F_SIZEOF_SIZE(f); /* Skip over local heap address */ + H5F_addr_decode(f, pp, &(oloc->addr)); + *pp += 4; /* Skip over "cache type" */ + *pp += 4; /* Reserved */ + } + + /* Common oloc settings */ oloc->holding_file = FALSE; - /* decode header */ - *pp += H5F_SIZEOF_SIZE(f); /* Skip over local heap address */ - H5F_addr_decode(f, pp, &(oloc->addr)); - *pp += 4; /* Skip over "cache type" */ - *pp += 4; /* Reserved */ - /* Set decode pointer */ *pp = p_ret + H5G_SIZEOF_ENTRY(f); - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_obj_ent_decode() */ diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index 31e5713..38c7628 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -100,14 +100,14 @@ typedef union H5G_cache_t { * also appears in the object header to which this symbol table entry * points. */ -typedef struct H5G_entry_t { +struct H5G_entry_t { hbool_t dirty; /*entry out-of-date? */ H5G_cache_type_t type; /*type of information cached */ H5G_cache_t cache; /*cached data from object header */ size_t name_off; /*offset of name within name heap */ haddr_t header; /*file address of object header */ H5F_t *file; /*file to which this obj hdr belongs */ -} H5G_entry_t; +}; /* * A symbol table node is a collection of symbol table entries. It can @@ -402,6 +402,10 @@ H5_DLL herr_t H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, hid_t dxpl_id); H5_DLL herr_t H5G_stab_lookup_by_idx(H5O_loc_t *grp_oloc, H5_iter_order_t order, hsize_t n, H5O_link_t *lnk, hid_t dxpl_id); +#ifndef H5_STRICT_FORMAT_CHECKS +H5_DLL herr_t H5G_stab_valid(H5O_loc_t *grp_oloc, hid_t dxpl_id, + H5O_stab_t *alt_stab); +#endif /* H5_STRICT_FORMAT_CHECKS */ #ifndef H5_NO_DEPRECATED_SYMBOLS H5_DLL H5G_obj_t H5G_stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id); diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 591be6b..b1db96f 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -145,6 +145,7 @@ typedef struct { typedef struct H5G_t H5G_t; typedef struct H5G_shared_t H5G_shared_t; +typedef struct H5G_entry_t H5G_entry_t; /* * Library prototypes... These are the ones that other packages routinely @@ -181,7 +182,7 @@ H5_DLL herr_t H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream * These functions operate on group object locations. */ H5_DLL herr_t H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp, - struct H5O_loc_t *oloc); + struct H5O_loc_t *oloc, H5G_entry_t **entp); H5_DLL herr_t H5G_obj_ent_encode(const H5F_t *f, uint8_t **pp, const struct H5O_loc_t *oloc); diff --git a/src/H5Gstab.c b/src/H5Gstab.c index f79d78b..c2df8e7 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -982,6 +982,81 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_stab_lookup_by_idx() */ +#ifndef H5_STRICT_FORMAT_CHECKS + +/*------------------------------------------------------------------------- + * Function: H5G_stab_valid + * + * Purpose: Verify that a group's symbol table message is valid. If + * provided, the addresses in alt_stab will be tried if the + * addresses in the group's stab message are invalid, and + * the stab message will be updated if necessary. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Neil Fortner + * nfortne2@hdfgroup.org + * Mar 17, 2009 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_stab_valid(H5O_loc_t *grp_oloc, hid_t dxpl_id, H5O_stab_t *alt_stab) +{ + H5O_stab_t stab; /* Current symbol table */ + H5HL_t *heap = NULL; /* Pointer to local heap */ + hbool_t changed = FALSE; /* Whether stab has been modified */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_stab_valid, FAIL) + + /* Read the symbol table message */ + H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id); + + /* Check if the symbol table message's b-tree address is valid */ + if(H5B_valid(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr) < 0) { + /* Address is invalid, try the b-tree address in the alternate symbol + * table message */ + if(!alt_stab || H5B_valid(grp_oloc->file, dxpl_id, H5B_SNODE, alt_stab->btree_addr) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to locate b-tree") + else { + /* The alternate symbol table's b-tree address is valid. Adjust the + * symbol table message in the group. */ + stab.btree_addr = alt_stab->btree_addr; + changed = TRUE; + } /* end else */ + } /* end if */ + + /* Check if the symbol table message's heap address is valid */ + if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_READ))) { + /* Address is invalid, try the heap address in the alternate symbol + * table message */ + if(!alt_stab || NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, alt_stab->heap_addr, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "unable to locate heap") + else { + /* The alternate symbol table's heap address is valid. Adjust the + * symbol table message in the group. */ + stab.heap_addr = alt_stab->heap_addr; + changed = TRUE; + } /* end else */ + } /* end if */ + + /* Update the symbol table message and clear errors if necessary */ + if(changed) { + H5E_clear_stack(NULL); + if(H5O_msg_write(grp_oloc, H5O_STAB_ID, 0, H5O_UPDATE_TIME | H5O_UPDATE_FORCE, &stab, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to correct symbol table message") + } /* end if */ + +done: + /* Release resources */ + if(heap && H5HL_unprotect(grp_oloc->file, dxpl_id, heap, stab.heap_addr) < 0) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_stab_valid */ +#endif /* H5_STRICT_FORMAT_CHECKS */ + #ifndef H5_NO_DEPRECATED_SYMBOLS /*------------------------------------------------------------------------- diff --git a/src/H5HFbtree2.c b/src/H5HFbtree2.c index eabb740..b750822 100644 --- a/src/H5HFbtree2.c +++ b/src/H5HFbtree2.c @@ -59,15 +59,6 @@ /* Local Prototypes */ /********************/ -/* v2 B-tree function callbacks */ -herr_t H5HF_huge_bt2_indir_found(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_indir_remove(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_filt_indir_found(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_filt_indir_remove(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_dir_remove(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_filt_dir_found(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_filt_dir_remove(const void *nrecord, void *op_data); - /* v2 B-tree driver callbacks */ static herr_t H5HF_huge_btree2_indir_store(void *native, const void *udata); static herr_t H5HF_huge_btree2_indir_retrieve(void *udata, const void *native); diff --git a/src/H5HFhuge.c b/src/H5HFhuge.c index db9f7a1..60c6c9f 100644 --- a/src/H5HFhuge.c +++ b/src/H5HFhuge.c @@ -69,13 +69,13 @@ static herr_t H5HF_huge_bt2_create(H5HF_hdr_t *hdr, hid_t dxpl_id); /* v2 B-tree function callbacks (in H5HFbtree2.c) */ -herr_t H5HF_huge_bt2_indir_found(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_indir_remove(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_filt_indir_found(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_filt_indir_remove(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_dir_remove(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_filt_dir_found(const void *nrecord, void *op_data); -herr_t H5HF_huge_bt2_filt_dir_remove(const void *nrecord, void *op_data); +H5_DLL herr_t H5HF_huge_bt2_indir_found(const void *nrecord, void *op_data); +H5_DLL herr_t H5HF_huge_bt2_indir_remove(const void *nrecord, void *op_data); +H5_DLL herr_t H5HF_huge_bt2_filt_indir_found(const void *nrecord, void *op_data); +H5_DLL herr_t H5HF_huge_bt2_filt_indir_remove(const void *nrecord, void *op_data); +H5_DLL herr_t H5HF_huge_bt2_dir_remove(const void *nrecord, void *op_data); +H5_DLL herr_t H5HF_huge_bt2_filt_dir_found(const void *nrecord, void *op_data); +H5_DLL herr_t H5HF_huge_bt2_filt_dir_remove(const void *nrecord, void *op_data); /* Local 'huge' object support routines */ static hsize_t H5HF_huge_new_id(H5HF_hdr_t *hdr); diff --git a/src/H5HFsection.c b/src/H5HFsection.c index 81b353f..91031be 100644 --- a/src/H5HFsection.c +++ b/src/H5HFsection.c @@ -3105,7 +3105,6 @@ H5HF_sect_indirect_reduce_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_ unsigned start_col; /* Start column in indirect block */ unsigned end_entry; /* Entry for last block covered */ unsigned end_row; /* End row in indirect block */ - unsigned end_col; /* End column in indirect block */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_reduce_row) @@ -3132,7 +3131,6 @@ HDfprintf(stderr, "%s: row_start_entry = %u, row_end_entry = %u\n", FUNC, row_st start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col; end_entry = (start_entry + sect->u.indirect.num_entries) - 1; end_row = end_entry / hdr->man_dtable.cparam.width; - end_col = end_entry % hdr->man_dtable.cparam.width; /* Additional sanity check */ HDassert(sect->u.indirect.span_size > 0); @@ -3144,7 +3142,7 @@ HDfprintf(stderr, "%s: row_start_entry = %u, row_end_entry = %u\n", FUNC, row_st HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); HDfprintf(stderr, "%s: sect->u.indirect.parent = %p, sect->u.indirect.par_entry = %u\n", FUNC, sect->u.indirect.parent, sect->u.indirect.par_entry); HDfprintf(stderr, "%s: start_entry = %u, start_row = %u, start_col = %u\n", FUNC, start_entry, start_row, start_col); -HDfprintf(stderr, "%s: end_entry = %u, end_row = %u, end_col = %u\n", FUNC, end_entry, end_row, end_col); +HDfprintf(stderr, "%s: end_entry = %u, end_row = %u\n", FUNC, end_entry, end_row); #endif /* QAK */ /* Check if we should allocate from end of indirect section */ @@ -3400,7 +3398,6 @@ H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *s unsigned start_col; /* Start column in indirect block */ unsigned end_entry; /* Entry for last block covered */ unsigned end_row; /* End row in indirect block */ - unsigned end_col; /* End column in indirect block */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_reduce) @@ -3422,12 +3419,11 @@ HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry); start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col; end_entry = (start_entry + sect->u.indirect.num_entries) - 1; end_row = end_entry / hdr->man_dtable.cparam.width; - end_col = end_entry % hdr->man_dtable.cparam.width; #ifdef QAK HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED")); HDfprintf(stderr, "%s: sect->u.indirect.parent = %p, sect->u.indirect.par_entry = %u\n", FUNC, sect->u.indirect.parent, sect->u.indirect.par_entry); HDfprintf(stderr, "%s: start_entry = %u, start_row = %u, start_col = %u\n", FUNC, start_entry, start_row, start_col); -HDfprintf(stderr, "%s: end_entry = %u, end_row = %u, end_col = %u\n", FUNC, end_entry, end_row, end_col); +HDfprintf(stderr, "%s: end_entry = %u, end_row = %u\n", FUNC, end_entry, end_row); #endif /* QAK */ /* Check how to adjust section for allocated entry */ @@ -3780,9 +3776,7 @@ H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id, unsigned start_row1, start_col1; /* Starting row & column for section #1 */ unsigned end_entry1; /* End entry for section #1 */ unsigned end_row1; /* Ending row for section #1 */ - unsigned start_entry2; /* Start entry for section #2 */ - unsigned start_row2, start_col2; /* Starting row & column for section #2 */ - unsigned end_entry2; /* End entry for section #2 */ + unsigned start_row2; /* Starting row for section #2 */ hbool_t merged_rows; /* Flag to indicate that rows was merged together */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -3831,12 +3825,9 @@ HDfprintf(stderr, "%s: sect1->u.indirect.num_entries = %u\n", FUNC, sect1->u.ind HDfprintf(stderr, "%s: end_row1 = %u, end_entry1 = %u\n", FUNC, end_row1, end_entry1); #endif /* QAK */ start_row2 = sect2->u.indirect.row; - start_col2 = sect2->u.indirect.col; - start_entry2 = (start_row2 * hdr->man_dtable.cparam.width) + start_col2; - end_entry2 = (start_entry2 + sect2->u.indirect.num_entries) - 1; #ifdef QAK HDfprintf(stderr, "%s: sect2->u.indirect.dir_nrows = %u\n", FUNC, sect2->u.indirect.dir_nrows); -HDfprintf(stderr, "%s: start_row2 = %u, start_col2 = %u, start_entry2 = %u\n", FUNC, start_row2, start_col2, start_entry2); +HDfprintf(stderr, "%s: start_row2 = %u\n", FUNC, start_row2); HDfprintf(stderr, "%s: sect2->u.indirect.num_entries = %u\n", FUNC, sect2->u.indirect.num_entries); #endif /* QAK */ diff --git a/src/H5HGdbg.c b/src/H5HGdbg.c index 43c1ed0..7030da5 100644 --- a/src/H5HGdbg.c +++ b/src/H5HGdbg.c @@ -113,7 +113,7 @@ H5HG_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, (unsigned long)H5HG_ALIGN(h->obj[u].size)); p = h->obj[u].begin + H5HG_SIZEOF_OBJHDR (f); for (j=0; j<h->obj[u].size; j+=16) { - fprintf (stream, "%*s%04d: ", indent+6, "", j); + fprintf (stream, "%*s%04u: ", indent+6, "", j); for (k=0; k<16; k++) { if (8==k) fprintf (stream, " "); if (j+k<h->obj[u].size) { diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c index 667f28c..e61d899 100644 --- a/src/H5Oainfo.c +++ b/src/H5Oainfo.c @@ -403,7 +403,7 @@ H5O_ainfo_pre_copy_file(H5F_t UNUSED *file_src, const void UNUSED *native_src, */ static void * H5O_ainfo_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, - hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id) + hbool_t *recompute_size, H5O_copy_t *cpy_info, void UNUSED *udata, hid_t dxpl_id) { H5O_ainfo_t *ainfo_src = (H5O_ainfo_t *)mesg_src; H5O_ainfo_t *ainfo_dst = NULL; @@ -467,7 +467,7 @@ static herr_t H5O_ainfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info) { - H5O_ainfo_t *ainfo_src = (const H5O_ainfo_t *)mesg_src; + const H5O_ainfo_t *ainfo_src = (const H5O_ainfo_t *)mesg_src; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_ainfo_post_copy_file) diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 24e443c..fe8c627 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -115,20 +115,23 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{ * * Purpose: Decodes a datatype * - * Return: Non-negative on success/Negative on failure + * Return: TRUE if we can upgrade the parent type's version even + * with strict format checks + * FALSE if we cannot + * Negative on failure * * Programmer: Robb Matzke * Monday, December 8, 1997 * *------------------------------------------------------------------------- */ -static herr_t +static htri_t H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **pp, H5T_t *dt) { unsigned flags, version; unsigned i; size_t z; - herr_t ret_value = SUCCEED; /* Return value */ + htri_t ret_value = FALSE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_dtype_decode_helper) @@ -254,6 +257,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p unsigned offset_nbytes; /* Size needed to encode member offsets */ size_t max_memb_pos = 0; /* Maximum member covered, so far */ unsigned max_version = 0; /* Maximum member version */ + hbool_t upgrade_to = 0; /* Version number we can "soft" upgrade to */ unsigned j; /* Compute the # of bytes required to store a member offset */ @@ -271,6 +275,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") for(i = 0; i < dt->shared->u.compnd.nmembs; i++) { unsigned ndims = 0; /* Number of dimensions of the array field */ + htri_t can_upgrade; /* Whether we can upgrade this type's version */ hsize_t dim[H5O_LAYOUT_NDIMS]; /* Dimensions of the array */ H5T_t *array_dt; /* Temporary pointer to the array datatype */ H5T_t *temp_type; /* Temporary pointer to the field's datatype */ @@ -318,16 +323,20 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Decode the field's datatype information */ - if(H5O_dtype_decode_helper(f, ioflags, pp, temp_type) < 0) { + if((can_upgrade = H5O_dtype_decode_helper(f, ioflags, pp, temp_type)) < 0) { for(j = 0; j <= i; j++) H5MM_xfree(dt->shared->u.compnd.memb[j].name); H5MM_xfree(dt->shared->u.compnd.memb); HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode member type") } /* end if */ - /* Keep track of the maximum member version found */ - if(temp_type->shared->version > max_version) - max_version = temp_type->shared->version; + /* Upgrade the version if we can and it is necessary */ + if(can_upgrade && temp_type->shared->version > version) { + upgrade_to = temp_type->shared->version; + + /* Pass "can_upgrade" flag down to parent type */ + ret_value = TRUE; + } /* end if */ /* Go create the array datatype now, for older versions of the datatype message */ if(version == H5O_DTYPE_VERSION_1) { @@ -346,9 +355,26 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p /* Make the array type the type that is set for the field */ temp_type = array_dt; + + /* Reset array version if NOCHANGE is specified (i.e. h5debug) */ + if(*ioflags & H5O_DECODEIO_NOCHANGE) + temp_type->shared->version = H5O_DTYPE_VERSION_1; + else { + /* Otherwise upgrade the compound version */ + if(upgrade_to < temp_type->shared->version) + upgrade_to = temp_type->shared->version; + + /* Set the return value to indicate that we should freely + * upgrade parent types */ + ret_value = TRUE; + } /* end else */ } /* end if */ } /* end if */ + /* Keep track of the maximum member version found */ + if(temp_type->shared->version > max_version) + max_version = temp_type->shared->version; + /* * Set the "force conversion" flag if VL datatype fields exist in this * type or any component types @@ -397,6 +423,17 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p dt->shared->u.compnd.packed = FALSE; } /* end if */ } /* end for */ + + /* Upgrade the compound if requested */ + if(version < upgrade_to) { + version = upgrade_to; + if(H5T_upgrade_version(dt, upgrade_to) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade compound encoding version") + /* We won't mark the message dirty since there were no + * errors in the file, simply type versions that we will no + * longer encode. */ + } /* end if */ + /* Check that no member of this compound has a version greater * than the compound itself. */ H5O_DTYPE_CHECK_VERSION(dt, version, max_version, ioflags, "compound", FAIL) @@ -1580,11 +1617,11 @@ H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream, "Version:", dt->shared->version); if (H5T_COMPOUND == dt->shared->type) { - fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, + fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Number of members:", dt->shared->u.compnd.nmembs); for(i = 0; i < dt->shared->u.compnd.nmembs; i++) { - sprintf(buf, "Member %d:", i); + sprintf(buf, "Member %u:", i); fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, buf, dt->shared->u.compnd.memb[i].name); @@ -1597,11 +1634,11 @@ H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream, } else if(H5T_ENUM == dt->shared->type) { fprintf(stream, "%*s%s\n", indent, "", "Base type:"); H5O_dtype_debug(f, dxpl_id, dt->shared->parent, stream, indent+3, MAX(0, fwidth-3)); - fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, + fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Number of members:", dt->shared->u.enumer.nmembs); for(i = 0; i < dt->shared->u.enumer.nmembs; i++) { - sprintf(buf, "Member %d:", i); + sprintf(buf, "Member %u:", i); fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, buf, dt->shared->u.enumer.name[i]); @@ -1678,7 +1715,7 @@ H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream, s = "disk"; break; default: - sprintf(buf, "H5T_LOC_%d", dt->shared->u.vlen.loc); + sprintf(buf, "H5T_LOC_%d", (int)dt->shared->u.vlen.loc); s = buf; break; } /* end switch */ @@ -1723,7 +1760,7 @@ H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream, s); } /* end if */ } else if(H5T_ARRAY == dt->shared->type) { - fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, + fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Rank:", dt->shared->u.array.ndims); fprintf(stream, "%*s%-*s {", indent, "", fwidth, "Dim Size:"); diff --git a/src/H5Omessage.c b/src/H5Omessage.c index 286240c..4a9ecb5 100644 --- a/src/H5Omessage.c +++ b/src/H5Omessage.c @@ -393,7 +393,7 @@ H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *ty HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message type not found") /* Check for modifying a constant message */ - if(idx_msg->flags & H5O_MSG_FLAG_CONSTANT) + if(!(update_flags & H5O_UPDATE_FORCE) && (idx_msg->flags & H5O_MSG_FLAG_CONSTANT)) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify constant message") /* This message is shared, but it's being modified. */ else if((idx_msg->flags & H5O_MSG_FLAG_SHARED) || (idx_msg->flags & H5O_MSG_FLAG_SHAREABLE)) { diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index c623b73..c2116bb 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -79,6 +79,7 @@ typedef struct H5O_t H5O_t; /* Flags for updating messages */ #define H5O_UPDATE_TIME 0x01u +#define H5O_UPDATE_FORCE 0x02u /* Force updating the message */ /* Hash value constants */ #define H5O_HASH_SIZE 32 @@ -55,25 +55,25 @@ H5FL_DEFINE_STATIC(H5RC_t); H5RC_t * H5RC_create(void *o, H5RC_free_func_t free_func) { - H5RC_t *ret_value=NULL; /* Return value */ + H5RC_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5RC_create,NULL); + FUNC_ENTER_NOAPI(H5RC_create, NULL) /* Sanity check */ HDassert(o); HDassert(free_func); /* Allocate ref-counted string structure */ - if((ret_value=H5FL_MALLOC(H5RC_t))==NULL) - HGOTO_ERROR(H5E_RS,H5E_NOSPACE,NULL,"memory allocation failed"); + if(NULL == (ret_value = H5FL_MALLOC(H5RC_t))) + HGOTO_ERROR(H5E_RS,H5E_NOSPACE,NULL,"memory allocation failed") /* Set the internal fields */ - ret_value->o=o; - ret_value->n=1; - ret_value->free_func=free_func; + ret_value->o = o; + ret_value->n = 1; + ret_value->free_func = free_func; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5RC_create() */ @@ -63,7 +63,7 @@ H5RS_xstrdup(const char *s) { char *ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5RS_xstrdup) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5RS_xstrdup) if(s) { ret_value = (char *)H5FL_BLK_MALLOC(str_buf, HDstrlen(s) + 1); @@ -99,21 +99,21 @@ H5RS_xstrdup(const char *s) H5RS_str_t * H5RS_create(const char *s) { - H5RS_str_t *ret_value=NULL; /* Return value */ + H5RS_str_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5RS_create,NULL); + FUNC_ENTER_NOAPI(H5RS_create, NULL) /* Allocate ref-counted string structure */ - if((ret_value=H5FL_MALLOC(H5RS_str_t))==NULL) - HGOTO_ERROR(H5E_RS,H5E_NOSPACE,NULL,"memory allocation failed"); + if(NULL == (ret_value = H5FL_MALLOC(H5RS_str_t))) + HGOTO_ERROR(H5E_RS, H5E_NOSPACE, NULL, "memory allocation failed") /* Set the internal fields */ - ret_value->s=H5RS_xstrdup(s); - ret_value->wrapped=0; - ret_value->n=1; + ret_value->s = H5RS_xstrdup(s); + ret_value->wrapped = 0; + ret_value->n = 1; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5RS_create() */ @@ -139,21 +139,21 @@ done: H5RS_str_t * H5RS_wrap(const char *s) { - H5RS_str_t *ret_value=NULL; /* Return value */ + H5RS_str_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5RS_wrap,NULL); + FUNC_ENTER_NOAPI(H5RS_wrap, NULL) /* Allocate ref-counted string structure */ - if((ret_value=H5FL_MALLOC(H5RS_str_t))==NULL) - HGOTO_ERROR(H5E_RS,H5E_NOSPACE,NULL,"memory allocation failed"); + if(NULL == (ret_value = H5FL_MALLOC(H5RS_str_t))) + HGOTO_ERROR(H5E_RS, H5E_NOSPACE, NULL, "memory allocation failed") /* Set the internal fields */ - ret_value->s=(char*)s; /* (Cast away const OK - QAK) */ - ret_value->wrapped=1; - ret_value->n=1; + ret_value->s = (char*)s; /* (Cast away const OK - QAK) */ + ret_value->wrapped = 1; + ret_value->n = 1; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5RS_wrap() */ @@ -181,21 +181,21 @@ done: H5RS_str_t * H5RS_own(char *s) { - H5RS_str_t *ret_value=NULL; /* Return value */ + H5RS_str_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5RS_own,NULL); + FUNC_ENTER_NOAPI(H5RS_own, NULL) /* Allocate ref-counted string structure */ - if((ret_value=H5FL_MALLOC(H5RS_str_t))==NULL) - HGOTO_ERROR(H5E_RS,H5E_NOSPACE,NULL,"memory allocation failed"); + if(NULL == (ret_value = H5FL_MALLOC(H5RS_str_t))) + HGOTO_ERROR(H5E_RS, H5E_NOSPACE, NULL, "memory allocation failed") /* Set the internal fields */ - ret_value->s=s; - ret_value->wrapped=0; - ret_value->n=1; + ret_value->s = s; + ret_value->wrapped = 0; + ret_value->n = 1; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5RS_own() */ @@ -259,25 +259,25 @@ H5RS_decr(H5RS_str_t *rs) herr_t H5RS_incr(H5RS_str_t *rs) { - FUNC_ENTER_NOAPI_NOFUNC(H5RS_incr); + FUNC_ENTER_NOAPI_NOFUNC(H5RS_incr) /* Sanity check */ - assert(rs); - assert(rs->n > 0); + HDassert(rs); + HDassert(rs->n > 0); /* If the ref-counted string started life as a wrapper around an existing * string, duplicate the string now, so that the wrapped string can go out * scope appropriately. */ if(rs->wrapped) { - rs->s=H5RS_xstrdup(rs->s); - rs->wrapped=0; + rs->s = H5RS_xstrdup(rs->s); + rs->wrapped = 0; } /* end if */ /* Increment reference count for string */ rs->n++; - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5RS_incr() */ @@ -303,14 +303,14 @@ H5RS_incr(H5RS_str_t *rs) H5RS_str_t * H5RS_dup(H5RS_str_t *ret_value) { - FUNC_ENTER_NOAPI_NOFUNC(H5RS_dup); + FUNC_ENTER_NOAPI_NOFUNC(H5RS_dup) /* Check for valid reference counted string */ - if(ret_value!=NULL) + if(ret_value != NULL) /* Increment reference count for string */ ret_value->n++; - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5RS_dup() */ @@ -335,7 +335,7 @@ H5RS_dup(H5RS_str_t *ret_value) H5RS_str_t * H5RS_dup_str(const char *s) { - char *new_str = NULL; /* Duplicate of string */ + char *new_str; /* Duplicate of string */ size_t path_len; /* Length of the path */ H5RS_str_t *ret_value; @@ -387,15 +387,15 @@ int H5RS_cmp(const H5RS_str_t *rs1, const H5RS_str_t *rs2) { /* Can't return invalid value from this function */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5RS_cmp); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5RS_cmp) /* Sanity check */ - assert(rs1); - assert(rs1->s); - assert(rs2); - assert(rs2->s); + HDassert(rs1); + HDassert(rs1->s); + HDassert(rs2); + HDassert(rs2->s); - FUNC_LEAVE_NOAPI(HDstrcmp(rs1->s,rs2->s)); + FUNC_LEAVE_NOAPI(HDstrcmp(rs1->s, rs2->s)) } /* end H5RS_cmp() */ @@ -420,13 +420,13 @@ H5RS_cmp(const H5RS_str_t *rs1, const H5RS_str_t *rs2) ssize_t H5RS_len(const H5RS_str_t *rs) { - FUNC_ENTER_NOAPI_NOFUNC(H5RS_len); + FUNC_ENTER_NOAPI_NOFUNC(H5RS_len) /* Sanity check */ - assert(rs); - assert(rs->s); + HDassert(rs); + HDassert(rs->s); - FUNC_LEAVE_NOAPI((ssize_t)HDstrlen(rs->s)); + FUNC_LEAVE_NOAPI((ssize_t)HDstrlen(rs->s)) } /* end H5RS_len() */ @@ -454,13 +454,13 @@ H5RS_len(const H5RS_str_t *rs) char * H5RS_get_str(const H5RS_str_t *rs) { - FUNC_ENTER_NOAPI_NOFUNC(H5RS_get_str); + FUNC_ENTER_NOAPI_NOFUNC(H5RS_get_str) /* Sanity check */ - assert(rs); - assert(rs->s); + HDassert(rs); + HDassert(rs->s); - FUNC_LEAVE_NOAPI(rs->s); + FUNC_LEAVE_NOAPI(rs->s) } /* end H5RS_get_str() */ @@ -486,12 +486,12 @@ H5RS_get_str(const H5RS_str_t *rs) unsigned H5RS_get_count(const H5RS_str_t *rs) { - FUNC_ENTER_NOAPI_NOFUNC(H5RS_get_count); + FUNC_ENTER_NOAPI_NOFUNC(H5RS_get_count) /* Sanity check */ - assert(rs); - assert(rs->n>0); + HDassert(rs); + HDassert(rs->n > 0); - FUNC_LEAVE_NOAPI(rs->n); + FUNC_LEAVE_NOAPI(rs->n) } /* end H5RS_get_count() */ @@ -50,19 +50,19 @@ H5FL_DEFINE_STATIC(H5ST_tree_t); H5ST_tree_t * H5ST_create(void) { - H5ST_tree_t *ret_value=NULL; /* Return value */ + H5ST_tree_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5ST_create,NULL); + FUNC_ENTER_NOAPI(H5ST_create, NULL) /* Allocate wrapper for TST */ - if((ret_value=H5FL_MALLOC(H5ST_tree_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,NULL,"memory allocation failed"); + if(NULL == (ret_value = H5FL_MALLOC(H5ST_tree_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Set the internal fields */ - ret_value->root=NULL; + ret_value->root = NULL; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5ST_create() */ @@ -178,16 +178,16 @@ H5ST_insert(H5ST_tree_t *tree, const char *s, void *obj) p = &tree->root; while((pp = *p)) { /* If this node matches the character in the key, then drop down to the lower tree */ - if ((d = *s - pp->splitchar) == 0) { - if (*s++ == 0) - HGOTO_ERROR(H5E_TST,H5E_EXISTS,FAIL,"key already in tree"); + if(0 == (d = *s - pp->splitchar)) { + if(*s++ == 0) + HGOTO_ERROR(H5E_TST, H5E_EXISTS, FAIL, "key already in tree") up=pp; p = &(pp->eqkid); } /* end if */ else { /* Walk through the current tree, searching for the matching character */ - parent=pp; - if (d < 0) + parent = pp; + if(d < 0) p = &(pp->lokid); else p = &(pp->hikid); @@ -196,8 +196,8 @@ H5ST_insert(H5ST_tree_t *tree, const char *s, void *obj) /* Finish walking through the key string, adding nodes until the end */ for (;;) { - if((*p = H5FL_MALLOC(H5ST_node_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,FAIL,"memory allocation failed"); + if(NULL == (*p = H5FL_MALLOC(H5ST_node_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") pp = *p; pp->splitchar = *s; pp->up = up; @@ -205,19 +205,19 @@ H5ST_insert(H5ST_tree_t *tree, const char *s, void *obj) pp->lokid = pp->eqkid = pp->hikid = NULL; /* If this is the end of the key string, break out */ - if (*s++ == 0) { - pp->eqkid = (H5ST_ptr_t) obj; + if(*s++ == 0) { + pp->eqkid = (H5ST_ptr_t)obj; break; } /* end if */ /* Continue to next character */ - parent=NULL; - up=pp; + parent = NULL; + up = pp; p = &(pp->eqkid); } /* end for */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5ST_insert() */ @@ -247,7 +247,7 @@ H5ST_search(H5ST_tree_t *tree, const char *s) H5ST_ptr_t p; /* Temporary pointer to TST node */ htri_t ret_value=FALSE; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5ST_search); + FUNC_ENTER_NOAPI_NOFUNC(H5ST_search) p = tree->root; while (p) { @@ -262,7 +262,7 @@ H5ST_search(H5ST_tree_t *tree, const char *s) } /* end while */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5ST_search() */ @@ -289,9 +289,9 @@ done: static H5ST_ptr_t H5ST_find_internal(H5ST_ptr_t p, const char *s) { - H5ST_ptr_t ret_value=NULL; /* Return value */ + H5ST_ptr_t ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_find_internal); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_find_internal) while (p) { if (*s < p->splitchar) @@ -305,7 +305,7 @@ H5ST_find_internal(H5ST_ptr_t p, const char *s) } /* end while */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5ST_find_internal() */ @@ -332,15 +332,15 @@ done: H5ST_ptr_t H5ST_find(H5ST_tree_t *tree, const char *s) { - H5ST_ptr_t ret_value=NULL; /* Return value */ + H5ST_ptr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5ST_find,NULL); + FUNC_ENTER_NOAPI(H5ST_find, NULL) - if((ret_value=H5ST_find_internal(tree->root,s))==NULL) - HGOTO_ERROR(H5E_TST,H5E_NOTFOUND,NULL,"key not found in TST"); + if(NULL == (ret_value = H5ST_find_internal(tree->root, s))) + HGOTO_ERROR(H5E_TST, H5E_NOTFOUND, NULL, "key not found in TST") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5ST_find() */ @@ -369,17 +369,17 @@ H5ST_locate(H5ST_tree_t *tree, const char *s) H5ST_ptr_t node; /* Pointer to node located */ void *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5ST_locate,NULL); + FUNC_ENTER_NOAPI(H5ST_locate, NULL) /* Locate the node to remove */ - if((node=H5ST_find_internal(tree->root,s))==NULL) - HGOTO_ERROR(H5E_TST,H5E_NOTFOUND,NULL,"key not found in TST"); + if(NULL == (node = H5ST_find_internal(tree->root, s))) + HGOTO_ERROR(H5E_TST, H5E_NOTFOUND, NULL, "key not found in TST") /* Get the pointer to the object to return */ - ret_value=node->eqkid; + ret_value = node->eqkid; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5ST_locate() */ @@ -404,28 +404,28 @@ done: static H5ST_ptr_t H5ST_findfirst_internal(H5ST_ptr_t p) { - H5ST_ptr_t ret_value=NULL; /* Return value */ + H5ST_ptr_t ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_findfirst_internal); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_findfirst_internal) while(p) { /* Find least node in current tree */ while(p->lokid) - p=p->lokid; + p = p->lokid; /* Is least node '\0'? */ - if(p->splitchar=='\0') { + if(p->splitchar == '\0') { /* Return it */ HGOTO_DONE(p); } /* end if */ else { /* Go down to next level of tree */ - p=p->eqkid; + p = p->eqkid; } /* end else */ } /* end while */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5ST_findfirst_internal() */ @@ -452,13 +452,13 @@ H5ST_findfirst(H5ST_tree_t *tree) { H5ST_ptr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5ST_findfirst,NULL); + FUNC_ENTER_NOAPI(H5ST_findfirst, NULL) - if((ret_value=H5ST_findfirst_internal(tree->root))==NULL) + if(NULL == (ret_value = H5ST_findfirst_internal(tree->root))) HGOTO_ERROR(H5E_TST,H5E_NOTFOUND,NULL,"no nodes in TST"); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5ST_findfirst() */ @@ -483,40 +483,40 @@ done: static H5ST_ptr_t H5ST_getnext(H5ST_ptr_t p) { - H5ST_ptr_t ret_value=NULL; /* Return value */ + H5ST_ptr_t ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_getnext); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_getnext) /* If the node to continue from has higher-valued nodes attached */ if(p->hikid) { /* Go to first higher-valued node */ - p=p->hikid; + p = p->hikid; /* Find least node from here */ while(p->lokid) - p=p->lokid; + p = p->lokid; HGOTO_DONE(p); } /* end if */ else { H5ST_ptr_t q; /* Temporary TST node pointer */ /* Go up one level in current tree */ - q=p->parent; - if(q==NULL) + q = p->parent; + if(q == NULL) HGOTO_DONE(NULL); /* While the previous node was the higher-valued node, keep backing up the tree */ - while(q->hikid==p) { - p=q; - q=p->parent; - if(q==NULL) + while(q->hikid == p) { + p = q; + q = p->parent; + if(NULL == q) HGOTO_DONE(NULL); } /* end while */ HGOTO_DONE(q); } /* end else */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5ST_getnext() */ @@ -542,22 +542,22 @@ H5ST_ptr_t H5ST_findnext(H5ST_ptr_t p) { H5ST_ptr_t q; /* Temporary pointer to TST node */ - H5ST_ptr_t ret_value=NULL; /* Return value */ + H5ST_ptr_t ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI_NOFUNC(H5ST_findnext); + FUNC_ENTER_NOAPI_NOFUNC(H5ST_findnext) /* Find the next node at the current level, or go back up the tree */ do { - q=H5ST_getnext(p); + q = H5ST_getnext(p); if(q) { HGOTO_DONE(H5ST_findfirst_internal(q->eqkid)); } /* end if */ else - p=p->up; + p = p->up; } while(p); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5ST_findnext() */ @@ -661,15 +661,15 @@ H5ST_delete_internal(H5ST_ptr_t *root, H5ST_ptr_t p) herr_t H5ST_delete(H5ST_tree_t *tree, H5ST_ptr_t p) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5ST_delete,FAIL); + FUNC_ENTER_NOAPI(H5ST_delete, FAIL) - if(H5ST_delete_internal(&tree->root,p)<0) - HGOTO_ERROR(H5E_TST,H5E_CANTDELETE,FAIL,"can't delete node from TST"); + if(H5ST_delete_internal(&tree->root, p) < 0) + HGOTO_ERROR(H5E_TST, H5E_CANTDELETE, FAIL, "can't delete node from TST") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5ST_delete() */ @@ -698,21 +698,21 @@ H5ST_remove(H5ST_tree_t *tree, const char *s) H5ST_ptr_t node; /* Pointer to node to remove */ void *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5ST_remove,NULL); + FUNC_ENTER_NOAPI(H5ST_remove, NULL) /* Locate the node to remove */ - if((node=H5ST_find_internal(tree->root,s))==NULL) - HGOTO_ERROR(H5E_TST,H5E_NOTFOUND,NULL,"key not found in TST"); + if(NULL == (node = H5ST_find_internal(tree->root, s))) + HGOTO_ERROR(H5E_TST, H5E_NOTFOUND, NULL, "key not found in TST") /* Get the pointer to the object to return */ - ret_value=node->eqkid; + ret_value = node->eqkid; /* Remove the node from the TST */ - if(H5ST_delete_internal(&tree->root,node)<0) - HGOTO_ERROR(H5E_TST,H5E_CANTDELETE,NULL,"can't delete node from TST"); + if(H5ST_delete_internal(&tree->root, node) < 0) + HGOTO_ERROR(H5E_TST, H5E_CANTDELETE, NULL, "can't delete node from TST") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5ST_remove() */ #ifdef H5ST_DEBUG @@ -738,26 +738,26 @@ done: herr_t H5ST_dump_internal(H5ST_ptr_t p) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_dump_internal); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_dump_internal) - if (p) { - printf("p=%p\n",p); - printf("\tp->up=%p\n",p->up); - printf("\tp->parent=%p\n",p->parent); - printf("\tp->lokid=%p\n",p->lokid); - printf("\tp->hikid=%p\n",p->hikid); - printf("\tp->eqkid=%p\n",p->eqkid); - printf("\tp->splitchar=%c\n",p->splitchar); + if(p) { + printf("p=%p\n", p); + printf("\tp->up=%p\n", p->up); + printf("\tp->parent=%p\n", p->parent); + printf("\tp->lokid=%p\n", p->lokid); + printf("\tp->hikid=%p\n", p->hikid); + printf("\tp->eqkid=%p\n", p->eqkid); + printf("\tp->splitchar=%c\n", p->splitchar); H5ST_dump_internal(p->lokid); - if (p->splitchar) + if(p->splitchar) H5ST_dump_internal(p->eqkid); else - printf("%s\n", (char *) p->eqkid); + printf("%s\n", (char *)p->eqkid); H5ST_dump_internal(p->hikid); } /* end if */ - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5ST_dump_internal() */ @@ -782,11 +782,12 @@ H5ST_dump_internal(H5ST_ptr_t p) herr_t H5ST_dump(H5ST_tree_t *tree) { - FUNC_ENTER_NOAPI_NOFUNC(H5ST_dump,NULL); + FUNC_ENTER_NOAPI_NOFUNC(H5ST_dump, NULL) /* Dump the tree */ H5ST_dump_internal(tree->root); - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5ST_dump() */ #endif /* H5ST_DEBUG */ + diff --git a/src/H5Smpio.c b/src/H5Smpio.c index 1f69706..72d61e6 100644 --- a/src/H5Smpio.c +++ b/src/H5Smpio.c @@ -107,17 +107,17 @@ H5S_mpio_all_type( const H5S_t *space, size_t elmt_size, hsize_t nelmts; /*total number of elmts */ herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_all_type); + FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_all_type) /* Check args */ - assert (space); + HDassert(space); /* Just treat the entire extent as a block of bytes */ - if((snelmts = H5S_GET_EXTENT_NPOINTS(space))<0) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src dataspace has invalid selection") - H5_ASSIGN_OVERFLOW(nelmts,snelmts,hssize_t,hsize_t); + if((snelmts = H5S_GET_EXTENT_NPOINTS(space)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "src dataspace has invalid selection") + H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, hsize_t); - total_bytes = (hsize_t)elmt_size*nelmts; + total_bytes = (hsize_t)elmt_size * nelmts; /* fill in the return values */ *new_type = MPI_BYTE; @@ -126,7 +126,7 @@ H5S_mpio_all_type( const H5S_t *space, size_t elmt_size, *is_derived_type = FALSE; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_mpio_all_type() */ @@ -210,7 +210,7 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, hbool_t *is_derived_type ) { H5S_sel_iter_t sel_iter; /* Selection iteration info */ - hbool_t sel_iter_init=0; /* Selection iteration info has been initialized */ + hbool_t sel_iter_init = FALSE; /* Selection iteration info has been initialized */ struct dim { /* less hassle than malloc/free & ilk */ hssize_t start; @@ -234,27 +234,27 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_hyper_type); /* Check args */ - assert (space); - assert(sizeof(MPI_Aint) >= sizeof(elmt_size)); - if (0==elmt_size) + HDassert(space); + HDassert(sizeof(MPI_Aint) >= sizeof(elmt_size)); + if(0 == elmt_size) goto empty; /* Initialize selection iterator */ - if (H5S_select_iter_init(&sel_iter, space, elmt_size)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - sel_iter_init=1; /* Selection iteration info has been initialized */ + if(H5S_select_iter_init(&sel_iter, space, elmt_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") + sel_iter_init = 1; /* Selection iteration info has been initialized */ /* Abbreviate args */ - diminfo=sel_iter.u.hyp.diminfo; - assert (diminfo); + diminfo = sel_iter.u.hyp.diminfo; + HDassert(diminfo); /* make a local copy of the dimension info so we can operate with them */ /* Check if this is a "flattened" regular hyperslab selection */ if(sel_iter.u.hyp.iter_rank!=0 && sel_iter.u.hyp.iter_rank<space->extent.rank) { /* Flattened selection */ - rank=sel_iter.u.hyp.iter_rank; - assert (rank >= 0 && rank<=H5S_MAX_RANK); /* within array bounds */ + rank = sel_iter.u.hyp.iter_rank; + HDassert(rank >= 0 && rank <= H5S_MAX_RANK); /* within array bounds */ if (0==rank) goto empty; #ifdef H5S_DEBUG @@ -288,7 +288,7 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size, else { /* Non-flattened selection */ rank = space->extent.rank; - assert (rank >= 0 && rank<=H5S_MAX_RANK); /* within array bounds */ + HDassert(rank >= 0 && rank<=H5S_MAX_RANK); /* within array bounds */ if (0==rank) goto empty; #ifdef H5S_DEBUG @@ -509,47 +509,39 @@ H5S_mpio_span_hyper_type( const H5S_t *space, MPI_Datatype *new_type,/* out: */ size_t *count, hsize_t *extra_offset, - hbool_t *is_derived_type ){ - - MPI_Datatype span_type; - H5S_hyper_span_t *ospan; - H5S_hyper_span_info_t *odown; - hsize_t *size; - int rank; - int mpi_code; - herr_t ret_value = SUCCEED; - MPI_Aint extent,lb; - - - FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_span_hyper_type); - - /* Check args */ - assert (space); + hbool_t *is_derived_type ) +{ - /* assert(sizeof(MPI_Aint) >= sizeof(elmt_size)); not sure the reason*/ + MPI_Datatype span_type; + H5S_hyper_span_t *ospan; + H5S_hyper_span_info_t *odown; + hsize_t *size; + int mpi_code; + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_span_hyper_type) - rank = space->extent.rank; + /* Check args */ + HDassert(space); - /* size = HDcalloc((size_t)rank,sizeof(hsize_t)); */ - if (0==elmt_size) + if(0 == elmt_size) goto empty; size = space->extent.size; - if(size == 0) + if(0 == size) goto empty; odown = space->select.sel_info.hslab->span_lst; - if(odown == NULL) - goto empty; + if(NULL == odown) + goto empty; ospan = odown->head; - if(ospan == NULL) - goto empty; + if(NULL == ospan) + goto empty; /* obtain derived data type */ - if(FAIL == H5S_obtain_datatype(space->extent.size,ospan,&span_type,elmt_size,rank)) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't obtain MPI derived data type"); + if(FAIL == H5S_obtain_datatype(space->extent.size, ospan, &span_type, elmt_size, space->extent.rank)) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't obtain MPI derived data type") - if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(&span_type))) + if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&span_type))) HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); *new_type = span_type; @@ -558,7 +550,7 @@ H5S_mpio_span_hyper_type( const H5S_t *space, *extra_offset = 0; *is_derived_type = TRUE; - HGOTO_DONE(SUCCEED); + HGOTO_DONE(SUCCEED) empty: /* special case: empty hyperslab */ @@ -568,8 +560,8 @@ empty: *is_derived_type = FALSE; done: - FUNC_LEAVE_NOAPI(ret_value); - } + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_mpio_span_hyper_type() */ /*------------------------------------------------------------------------- @@ -585,173 +577,162 @@ done: * Programmer: kyang * */ -static herr_t H5S_obtain_datatype(const hsize_t size[], +static herr_t +H5S_obtain_datatype(const hsize_t size[], H5S_hyper_span_t* span, MPI_Datatype *span_type, size_t elmt_size, int dimindex) { - - int innercount,outercount; - MPI_Datatype bas_type; - MPI_Datatype temp_type; - MPI_Datatype tempinner_type; - MPI_Datatype *inner_type; - int *blocklen; - MPI_Aint *disp; - MPI_Aint stride; - MPI_Aint extent,lb; - H5S_hyper_span_info_t *down; - H5S_hyper_span_t *tspan; - int mpi_code; - herr_t ret_value = SUCCEED; - + int innercount, outercount; + MPI_Datatype bas_type; + MPI_Datatype temp_type; + MPI_Datatype tempinner_type; + MPI_Datatype *inner_type; + int *blocklen; + MPI_Aint *disp; + MPI_Aint stride; + H5S_hyper_span_info_t *down; + H5S_hyper_span_t *tspan; #ifdef H5_HAVE_MPI2 - MPI_Aint sizeaint,sizedtype; + MPI_Aint sizeaint, sizedtype; #endif /* H5_HAVE_MPI2 */ - hsize_t total_lowd,total_lowd1; - int i; - int ret; - - FUNC_ENTER_NOAPI_NOINIT(H5S_obtain_datatype); - assert(span); - - inner_type = NULL; - down = NULL; - tspan = NULL; - down = span->down; - tspan = span; - - outercount = 0; - -/* obtain the number of span tree for this dimension */ - while(tspan) { - tspan = tspan->next; - outercount ++; - } - - if(outercount == 0) { - span_type = NULL; - return 0; - } + hsize_t total_lowd, total_lowd1; + int i; + int mpi_code; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5S_obtain_datatype) + + HDassert(span); + + inner_type = NULL; + down = NULL; + tspan = NULL; + down = span->down; + tspan = span; + + /* obtain the number of span tree for this dimension */ + outercount = 0; + while(tspan) { + tspan = tspan->next; + outercount++; + } /* end while */ + if(outercount == 0) + HGOTO_DONE(SUCCEED) /* MPI2 hasn't been widely acccepted, adding H5_HAVE_MPI2 for the future use */ #ifdef H5_HAVE_MPI2 - MPI_Type_extent(MPI_Aint,&sizeaint); - MPI_Type_extent(MPI_Datatype,&sizedtype); + MPI_Type_extent(MPI_Aint, &sizeaint); + MPI_Type_extent(MPI_Datatype, &sizedtype); - blocklen = (int *)HDcalloc((size_t)outercount,sizeof(int)); - disp = (MPI_Aint *)HDcalloc((size_t)outercount,sizeaint); - inner_type = (MPI_Datatype *)HDcalloc((size_t)outercount,sizedtype); + blocklen = (int *)HDcalloc((size_t)outercount, sizeof(int)); + disp = (MPI_Aint *)HDcalloc((size_t)outercount, sizeaint); + inner_type = (MPI_Datatype *)HDcalloc((size_t)outercount, sizedtype); #else - blocklen = (int *)HDcalloc((size_t)outercount,sizeof(int)); - disp = (MPI_Aint *)HDcalloc((size_t)outercount,sizeof(MPI_Aint)); - inner_type = (MPI_Datatype *)HDcalloc((size_t)outercount,sizeof(MPI_Datatype)); + blocklen = (int *)HDcalloc((size_t)outercount, sizeof(int)); + disp = (MPI_Aint *)HDcalloc((size_t)outercount, sizeof(MPI_Aint)); + inner_type = (MPI_Datatype *)HDcalloc((size_t)outercount, sizeof(MPI_Datatype)); #endif - tspan = span; - outercount = 0; + tspan = span; + outercount = 0; - /* if this is the fastest changing dimension, it is the base case for derived datatype. */ - if(down == NULL){ + /* if this is the fastest changing dimension, it is the base case for derived datatype. */ + if(down == NULL){ - assert(dimindex <= 1); - if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE,&bas_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code); + HDassert(dimindex <= 1); - if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&bas_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); + if(MPI_SUCCESS != (mpi_code = MPI_Type_contiguous((int)elmt_size, MPI_BYTE,&bas_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code); - while(tspan){ + if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&bas_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); - disp[outercount] = (MPI_Aint)elmt_size * tspan->low; - blocklen[outercount] = tspan->nelem; - tspan = tspan->next; - outercount ++; - } + while(tspan) { + disp[outercount] = (MPI_Aint)elmt_size * tspan->low; + blocklen[outercount] = tspan->nelem; + tspan = tspan->next; + outercount++; + } /* end while */ - if(MPI_SUCCESS != (mpi_code = MPI_Type_hindexed(outercount,blocklen, - disp,bas_type,span_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_hindexed failed", mpi_code); + if(MPI_SUCCESS != (mpi_code = MPI_Type_hindexed(outercount, blocklen, disp, bas_type, span_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_hindexed failed", mpi_code); + } /* end if */ + else {/* dimindex is the rank of the dimension */ - } - else {/* dimindex is the rank of the dimension */ + HDassert(dimindex > 1); - assert(dimindex >1); - /* Calculate the total bytes of the lower dimension */ - total_lowd = 1; /* one dimension down */ - total_lowd1 = 1; /* two dimensions down */ + /* Calculate the total bytes of the lower dimension */ + total_lowd = 1; /* one dimension down */ + total_lowd1 = 1; /* two dimensions down */ - for ( i = dimindex-1; i > 0; i--) - total_lowd = total_lowd * size[i]; + for ( i = dimindex-1; i > 0; i--) + total_lowd = total_lowd * size[i]; - for ( i = dimindex-1; i > 1; i--) - total_lowd1 = total_lowd1 * size[i]; + for ( i = dimindex-1; i > 1; i--) + total_lowd1 = total_lowd1 * size[i]; - while(tspan){ + while(tspan) { - /* Displacement should be in byte and should have dimension information */ - /* First using MPI Type vector to build derived data type for this span only */ - /* Need to calculate the disp in byte for this dimension. */ - /* Calculate the total bytes of the lower dimension */ + /* Displacement should be in byte and should have dimension information */ + /* First using MPI Type vector to build derived data type for this span only */ + /* Need to calculate the disp in byte for this dimension. */ + /* Calculate the total bytes of the lower dimension */ - disp[outercount] = tspan->low*total_lowd*elmt_size; - blocklen[outercount] = 1; + disp[outercount] = tspan->low*total_lowd*elmt_size; + blocklen[outercount] = 1; - /* generating inner derived datatype by using MPI_Type_hvector */ - if(FAIL == H5S_obtain_datatype(size,tspan->down->head,&temp_type,elmt_size,dimindex-1)) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't obtain MPI derived data type"); + /* generating inner derived datatype by using MPI_Type_hvector */ + if(FAIL == H5S_obtain_datatype(size,tspan->down->head,&temp_type,elmt_size,dimindex-1)) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't obtain MPI derived data type") - if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&temp_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); + if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&temp_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); - /* building the inner vector datatype */ - stride = total_lowd*elmt_size; - innercount = tspan->nelem; + /* building the inner vector datatype */ + stride = total_lowd*elmt_size; + innercount = tspan->nelem; - if(MPI_SUCCESS != (mpi_code = MPI_Type_hvector(innercount,1,stride,temp_type,&tempinner_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_hvector failed", mpi_code); + if(MPI_SUCCESS != (mpi_code = MPI_Type_hvector(innercount,1,stride,temp_type,&tempinner_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_hvector failed", mpi_code); - if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&tempinner_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); + if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&tempinner_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code); - if(MPI_SUCCESS != (mpi_code =MPI_Type_free(&temp_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed",mpi_code); - inner_type[outercount] = tempinner_type; - outercount ++; - tspan = tspan->next; + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&temp_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code); - } + inner_type[outercount] = tempinner_type; + outercount ++; + tspan = tspan->next; + } /* end while */ - /* building the whole vector datatype */ - if(MPI_SUCCESS != (mpi_code = - MPI_Type_struct(outercount,blocklen,disp,inner_type,span_type))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code); - - } + /* building the whole vector datatype */ + if(MPI_SUCCESS != (mpi_code = MPI_Type_struct(outercount, blocklen, disp, inner_type, span_type))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code); + } /* end else */ - if(inner_type != NULL){ - if(down != NULL) { - for(i=0;i<outercount;i++) - if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&inner_type[i]))) - HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed",mpi_code); - } - } + if(inner_type != NULL && down != NULL) { + for(i = 0; i < outercount; i++) + if(MPI_SUCCESS != (mpi_code = MPI_Type_free(&inner_type[i]))) + HMPI_GOTO_ERROR(FAIL, "MPI_Type_free failed", mpi_code); + } /* end if */ - if(inner_type != NULL) - HDfree(inner_type); - if(blocklen != NULL) - HDfree(blocklen); - if(disp != NULL) - HDfree(disp); + if(inner_type != NULL) + HDfree(inner_type); + if(blocklen != NULL) + HDfree(blocklen); + if(disp != NULL) + HDfree(disp); done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_obtain_datatype() */ @@ -791,7 +772,7 @@ H5S_mpio_space_type( const H5S_t *space, size_t elmt_size, FUNC_ENTER_NOAPI_NOINIT(H5S_mpio_space_type); /* Check args */ - assert (space); + HDassert(space); /* Creat MPI type based on the kind of selection */ switch (H5S_GET_EXTENT_TYPE(space)) { @@ -830,13 +811,13 @@ H5S_mpio_space_type( const H5S_t *space, size_t elmt_size, break; default: - assert("unknown selection type" && 0); + HDassert("unknown selection type" && 0); break; } /* end switch */ break; default: - assert("unknown data space type" && 0); + HDassert("unknown data space type" && 0); break; } @@ -845,3 +826,4 @@ done: } #endif /* H5_HAVE_PARALLEL */ + @@ -271,17 +271,17 @@ done: herr_t H5Z_register (const H5Z_class_t *cls) { - size_t i; - herr_t ret_value=SUCCEED; /* Return value */ + size_t i; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5Z_register, FAIL) - assert (cls); - assert (cls->id>=0 && cls->id<=H5Z_FILTER_MAX); + HDassert(cls); + HDassert(cls->id >= 0 && cls->id <= H5Z_FILTER_MAX); /* Is the filter already registered? */ - for (i=0; i<H5Z_table_used_g; i++) - if (H5Z_table_g[i].id==cls->id) + for(i = 0; i < H5Z_table_used_g; i++) + if(H5Z_table_g[i].id == cls->id) break; /* Filter not already registered */ @@ -572,7 +572,7 @@ H5Z_prelude_callback(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_ty break; default: - assert("invalid prelude type" && 0); + HDassert("invalid prelude type" && 0); } /* end switch */ } /* end else */ } /* end for */ diff --git a/src/H5err.txt b/src/H5err.txt index 7f110b8..64e9729 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -169,6 +169,8 @@ MINOR, CACHE, H5E_CANTMARKDIRTY, Unable to mark a pinned entry as dirty MINOR, CACHE, H5E_CANTDIRTY, Unable to mark metadata as dirty MINOR, CACHE, H5E_CANTEXPUNGE, Unable to expunge a metadata cache entry MINOR, CACHE, H5E_CANTRESIZE, Unable to resize a metadata cache entry +MINOR, CACHE, H5E_CANTDEPEND, Unable to create a flush dependency +MINOR, CACHE, H5E_CANTUNDEPEND, Unable to destroy a flush dependency # B-tree related errors MINOR, BTREE, H5E_NOTFOUND, Object not found diff --git a/src/H5private.h b/src/H5private.h index ea55a61..695b015 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -1898,6 +1898,11 @@ static herr_t H5_INTERFACE_INIT_FUNC(void); } /*end scope from beginning of FUNC_ENTER*/ +/* Macro for "stringizing" an integer in the C preprocessor (use H5_TOSTRING) */ +/* (use H5_TOSTRING, H5_STRINGIZE is just part of the implementation) */ +#define H5_STRINGIZE(x) #x +#define H5_TOSTRING(x) H5_STRINGIZE(x) + /* Macro for "glueing" together items, for re-scanning macros */ #define H5_GLUE(x,y) x##y #define H5_GLUE3(x,y,z) x##y##z diff --git a/src/H5public.h b/src/H5public.h index e0a9049..ab471b9 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -71,10 +71,10 @@ extern "C" { /* Version numbers */ #define H5_VERS_MAJOR 1 /* For major interface/format changes */ #define H5_VERS_MINOR 9 /* For minor interface/format changes */ -#define H5_VERS_RELEASE 34 /* For tweaks, bug-fixes, or development */ +#define H5_VERS_RELEASE 36 /* For tweaks, bug-fixes, or development */ #define H5_VERS_SUBRELEASE "" /* For pre-releases like snap0 */ /* Empty string for real releases. */ -#define H5_VERS_INFO "HDF5 library version: 1.9.34" /* Full version string */ +#define H5_VERS_INFO "HDF5 library version: 1.9.36" /* Full version string */ #define H5check() H5check_version(H5_VERS_MAJOR,H5_VERS_MINOR, \ H5_VERS_RELEASE) diff --git a/src/Makefile.in b/src/Makefile.in index e49d68b..5433176 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -328,6 +328,8 @@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ + +# Install directories that automake doesn't know about docdir = $(exec_prefix)/doc dvidir = @dvidir@ enable_shared = @enable_shared@ @@ -339,9 +341,7 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ - -# Install directories that automake doesn't know about -includedir = $(exec_prefix)/include +includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ @@ -409,7 +409,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog # Add libtool shared library version numbers to the HDF5 library # See libtool versioning documentation online. LT_VERS_INTERFACE = 6 -LT_VERS_REVISION = 24 +LT_VERS_REVISION = 26 LT_VERS_AGE = 0 H5detect_CFLAGS = -g |