diff options
author | Neil Fortner <nfortne2@hdfgroup.org> | 2011-10-13 23:10:50 (GMT) |
---|---|---|
committer | Neil Fortner <nfortne2@hdfgroup.org> | 2011-10-13 23:10:50 (GMT) |
commit | 56960ac85c40c3b08989ff776d2a69c6e79a6f09 (patch) | |
tree | bc1aeb7b0a4e8f9ee1d731524d904022b4f1e2d7 /src/H5SM.c | |
parent | 1406da6362e460a6dc5a3882ec0f62dca159b9a5 (diff) | |
download | hdf5-56960ac85c40c3b08989ff776d2a69c6e79a6f09.zip hdf5-56960ac85c40c3b08989ff776d2a69c6e79a6f09.tar.gz hdf5-56960ac85c40c3b08989ff776d2a69c6e79a6f09.tar.bz2 |
[svn-r21556] Purpose: Fix bug in H5Ocopy
Description:
H5Ocopy could get confused when copying a named datatype containing an
attribute which used that named datatype as its datatype. This happened
because H5Ocopy would recurse into the attribute's datatype before the object
the attribute was in was fully copied (i.e. before the "post-copy" pass).
Modified H5Ocopy to avoid recursing before the post-copy step in this case.
Required many changes, including to how non-committed shared messages are
copied.
Tested: jam, koala, heiwa (h5committest); durandal
Diffstat (limited to 'src/H5SM.c')
-rwxr-xr-x | src/H5SM.c | 266 |
1 files changed, 159 insertions, 107 deletions
@@ -65,7 +65,7 @@ static herr_t H5SM_convert_list_to_btree(H5F_t * f, H5SM_index_header_t * header static herr_t H5SM_convert_btree_to_list(H5F_t * f, H5SM_index_header_t * header, hid_t dxpl_id); static herr_t H5SM_incr_ref(void *record, void *_op_data, hbool_t *changed); static herr_t H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, - H5SM_index_header_t *header, unsigned type_id, void *mesg, + H5SM_index_header_t *header, hbool_t defer, unsigned type_id, void *mesg, unsigned *cache_flags_ptr); static herr_t H5SM_decr_ref(void *record, void *op_data, hbool_t *changed); static herr_t H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, @@ -988,6 +988,10 @@ done: * header it needs (which can cause an error if that OH is * already protected!). * + * The DEFER flag indicates whether the sharing operation + * should actually occur, or whether this is just a set up call + * for a future sharing operation. + * * MESG_FLAGS will have the H5O_MSG_FLAG_SHAREABLE or * H5O_MSG_FLAG_SHARED flag set if one is appropriate. This is * the only way to tell the difference between a message that @@ -1025,8 +1029,8 @@ done: *------------------------------------------------------------------------- */ htri_t -H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id, - void *mesg, unsigned *mesg_flags) +H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, hbool_t defer, + unsigned type_id, void *mesg, unsigned *mesg_flags) { H5SM_master_table_t *table = NULL; H5SM_table_cache_ud_t cache_udata; /* User-data for callback */ @@ -1071,13 +1075,13 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned type_id, * message to become shared (if it is unique, it will not be shared). */ if(H5SM_write_mesg(f, dxpl_id, open_oh, &(table->indexes[index_num]), - type_id, mesg, &cache_flags) < 0) + defer, type_id, mesg, &cache_flags) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "can't write shared message") - /* Set flags if this message was "written" without error; it is now - * either fully shared or "shareable". + /* Set flags if this message was "written" without error and wasn't a + * 'defer' attempt; it is now either fully shared or "shareable". */ - if(mesg_flags) { + if(mesg_flags && !defer) { if(((H5O_shared_t *)mesg)->type == H5O_SHARE_TYPE_HERE) *mesg_flags |= H5O_MSG_FLAG_SHAREABLE; else @@ -1157,19 +1161,28 @@ done: /*------------------------------------------------------------------------- * Function: H5SM_write_mesg * - * Purpose: Adds a shareable message to an index. If this is the first - * such message and we have an object header location for this - * message, we record it in the index but don't modify the - * message passed in. - * - * If the message is already in the index or we don't have an - * object header location for it, it is shared in the heap - * and this function sets its sharing struct to reflect this. + * Purpose: This routine adds a shareable message to an index. + * The behavior is controlled by the DEFER parameter: + * + * If DEFER is TRUE, this routine Simulates adding a shareable + * message to an index. It determines what the outcome would + * be with DEFER set the FALSE and updates the shared message + * info, but does not actually add the message to a heap, list, + * or b-tree. Assumes that an open object header will be + * available when H5SM_write_mesg is called with DEFER set to + * FALSE. + * + * If DEFER is FALSE, this routine adds a shareable message to + * an index. If this is the first such message and we have an + * object header location for this message, we record it in the + * index but don't modify the message passed in. If the message + * is already in the index or we don't have an object header + * location for it, it is shared in the heap and this function + * sets its sharing struct to reflect this. * * The index could be a list or a B-tree. * - * Return: TRUE if message is now shared - * FALSE if message is in index but is not shared + * Return: Non-negative on success * Negative on failure * * Programmer: James Laird @@ -1179,7 +1192,7 @@ done: */ static herr_t H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, - H5SM_index_header_t *header, unsigned type_id, void *mesg, + H5SM_index_header_t *header, hbool_t defer, unsigned type_id, void *mesg, unsigned *cache_flags_ptr) { H5SM_list_t *list = NULL; /* List index */ @@ -1234,7 +1247,7 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, cache_udata.header = header; /* The index is a list; get it from the cache */ - if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &cache_udata, H5AC_WRITE))) + if(NULL == (list = (H5SM_list_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, &cache_udata, defer ? H5AC_READ : H5AC_WRITE))) HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM index") /* See if the message is already in the index and get its location. @@ -1242,55 +1255,75 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, * later. */ list_pos = H5SM_find_in_list(list, &key, &empty_pos); - if(list_pos != UFAIL) { - /* If the message was previously shared in an object header, share - * it in the heap now. - */ - if(list->messages[list_pos].location == H5SM_IN_OH) { - /* Put the message in the heap and record its new heap ID */ - if(H5HF_insert(fheap, dxpl_id, key.encoding_size, key.encoding, &shared.u.heap_id) < 0) - HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") - - list->messages[list_pos].location = H5SM_IN_HEAP; - list->messages[list_pos].u.heap_loc.fheap_id = shared.u.heap_id; - list->messages[list_pos].u.heap_loc.ref_count = 2; - } /* end if */ - else { - /* If the message was already in the heap, increase its ref count */ - HDassert(list->messages[list_pos].location == H5SM_IN_HEAP); - ++(list->messages[list_pos].u.heap_loc.ref_count); - } /* end else */ - - /* Set up the shared location to point to the shared location */ - shared.u.heap_id = list->messages[list_pos].u.heap_loc.fheap_id; - found = TRUE; + if(defer) { + if(list_pos != UFAIL) + found = TRUE; } /* end if */ + else { + if(list_pos != UFAIL) { + /* If the message was previously shared in an object header, share + * it in the heap now. + */ + if(list->messages[list_pos].location == H5SM_IN_OH) { + /* Put the message in the heap and record its new heap ID */ + if(H5HF_insert(fheap, dxpl_id, key.encoding_size, key.encoding, &shared.u.heap_id) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") + + list->messages[list_pos].location = H5SM_IN_HEAP; + list->messages[list_pos].u.heap_loc.fheap_id = shared.u.heap_id; + list->messages[list_pos].u.heap_loc.ref_count = 2; + } /* end if */ + else { + /* If the message was already in the heap, increase its ref count */ + HDassert(list->messages[list_pos].location == H5SM_IN_HEAP); + ++(list->messages[list_pos].u.heap_loc.ref_count); + } /* end else */ + + /* Set up the shared location to point to the shared location */ + shared.u.heap_id = list->messages[list_pos].u.heap_loc.fheap_id; + found = TRUE; + } /* end if */ + } /* end else */ } /* end if */ /* Index is a B-tree */ else { - H5SM_incr_ref_opdata op_data; - HDassert(header->index_type == H5SM_BTREE); /* Open the index v2 B-tree */ if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f))) HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index") - /* Set up callback info */ - op_data.key = &key; - op_data.dxpl_id = dxpl_id; + if(defer) { + htri_t bt2_find; /* Result from searching in the v2 B-tree */ - /* If this returns failure, it means that the message wasn't found. */ - /* If it succeeds, set the heap_id in the shared struct. It will - * return a heap ID, since a message with a reference count greater - * than 1 is always shared in the heap. - */ - if(H5B2_modify(bt2, dxpl_id, &key, H5SM_incr_ref, &op_data) >= 0) { - shared.u.heap_id = op_data.fheap_id; - found = TRUE; + /* If this returns 0, it means that the message wasn't found. */ + /* If it return 1, set the heap_id in the shared struct. It will + * return a heap ID, since a message with a reference count greater + * than 1 is always shared in the heap. + */ + if((bt2_find = H5B2_find(bt2, dxpl_id, &key, NULL, NULL)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "can't search for message in index") + found = (hbool_t)bt2_find; } /* end if */ - else - H5E_clear_stack(NULL); /*ignore error*/ + else { + H5SM_incr_ref_opdata op_data; + + /* Set up callback info */ + op_data.key = &key; + op_data.dxpl_id = dxpl_id; + + /* If this returns failure, it means that the message wasn't found. */ + /* If it succeeds, set the heap_id in the shared struct. It will + * return a heap ID, since a message with a reference count greater + * than 1 is always shared in the heap. + */ + if(H5B2_modify(bt2, dxpl_id, &key, H5SM_incr_ref, &op_data) >= 0) { + shared.u.heap_id = op_data.fheap_id; + found = TRUE; + } /* end if */ + else + H5E_clear_stack(NULL); /*ignore error*/ + } /* end else */ } /* end else */ if(found) @@ -1308,75 +1341,94 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "'share in ohdr' check returned error") /* If this message can be shared in an object header location, it is - * "shareable" but not shared in the heap. Insert it in the index - * but don't modify the original message. + * "shareable" but not shared in the heap. + * + * If 'defer' flag is set: + * We will insert it in the index but not modify the original + * message. + * If it can't be shared in an object header location, we will + * insert it in the heap. Note that we assume there will + * be an "open_oh" available when it is time to call + * H5SM_write_mesg with defer flag disabled. * - * If it can't be shared in an object header location or there's no - * object header location available, insert it in the heap. + * If 'defer' flag is not set: + * Insert it in the index but don't modify the original message. + * If it can't be shared in an object header location or there's + * no object header location available, insert it in the + * heap. */ - if(share_in_ohdr && open_oh) { + if(share_in_ohdr && (defer || open_oh)) { /* Set up shared component info */ shared.type = H5O_SHARE_TYPE_HERE; /* Retrieve any creation index from the native message */ if(H5O_msg_get_crt_index(type_id, mesg, &shared.u.loc.index) < 0) HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "unable to retrieve creation index") - shared.u.loc.oh_addr = H5O_OH_GET_ADDR(open_oh); - /* Copy shared component info into key for inserting into index */ - key.message.location = H5SM_IN_OH; - key.message.u.mesg_loc = shared.u.loc; + if(defer) + shared.u.loc.oh_addr = HADDR_UNDEF; + else { + shared.u.loc.oh_addr = H5O_OH_GET_ADDR(open_oh); + + /* Copy shared component info into key for inserting into index */ + key.message.location = H5SM_IN_OH; + key.message.u.mesg_loc = shared.u.loc; + } /* end else */ } /* end if */ else { - /* Put the message in the heap and record its new heap ID */ - if(H5HF_insert(fheap, dxpl_id, key.encoding_size, key.encoding, &shared.u.heap_id) < 0) - HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") - /* Set up shared component info */ - /* (heap ID set above) */ + /* (heap ID set below, if not deferred) */ shared.type = H5O_SHARE_TYPE_SOHM; - key.message.location = H5SM_IN_HEAP; - key.message.u.heap_loc.fheap_id = shared.u.heap_id; - key.message.u.heap_loc.ref_count = 1; - } /* end else */ - - /* Set common information */ - key.message.msg_type_id = type_id; + if(!defer) { + /* Put the message in the heap and record its new heap ID */ + if(H5HF_insert(fheap, dxpl_id, key.encoding_size, key.encoding, &shared.u.heap_id) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap") - /* Check whether the list has grown enough that it needs to become a B-tree */ - if(header->index_type == H5SM_LIST && header->num_messages >= header->list_max) - if(H5SM_convert_list_to_btree(f, header, &list, fheap, open_oh, dxpl_id) < 0) - HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to convert list to B-tree") - - /* Insert the new message into the SOHM index */ - if(header->index_type == H5SM_LIST) { - /* Index is a list. Find an empty spot if we haven't already */ - if(empty_pos == UFAIL) - if((H5SM_find_in_list(list, NULL, &empty_pos) == UFAIL) || empty_pos == UFAIL) - HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to find empty entry in list") - - /* Insert message into list */ - HDassert(list->messages[empty_pos].location == H5SM_NO_LOC); - HDassert(key.message.location != H5SM_NO_LOC); - list->messages[empty_pos] = key.message; - } /* end if */ - /* Index is a B-tree */ - else { - HDassert(header->index_type == H5SM_BTREE); + key.message.location = H5SM_IN_HEAP; + key.message.u.heap_loc.fheap_id = shared.u.heap_id; + key.message.u.heap_loc.ref_count = 1; + } /* end if */ + } /* end else */ - /* Open the index v2 B-tree, if it isn't already */ - if(NULL == bt2) { - if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f))) - HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index") + if(!defer) { + /* Set common information */ + key.message.msg_type_id = type_id; + + /* Check whether the list has grown enough that it needs to become a B-tree */ + if(header->index_type == H5SM_LIST && header->num_messages >= header->list_max) + if(H5SM_convert_list_to_btree(f, header, &list, fheap, open_oh, dxpl_id) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to convert list to B-tree") + + /* Insert the new message into the SOHM index */ + if(header->index_type == H5SM_LIST) { + /* Index is a list. Find an empty spot if we haven't already */ + if(empty_pos == UFAIL) + if((H5SM_find_in_list(list, NULL, &empty_pos) == UFAIL) || empty_pos == UFAIL) + HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "unable to find empty entry in list") + + /* Insert message into list */ + HDassert(list->messages[empty_pos].location == H5SM_NO_LOC); + HDassert(key.message.location != H5SM_NO_LOC); + list->messages[empty_pos] = key.message; } /* end if */ + /* Index is a B-tree */ + else { + HDassert(header->index_type == H5SM_BTREE); - if(H5B2_insert(bt2, dxpl_id, &key) < 0) - HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "couldn't add SOHM to B-tree") - } /* end else */ + /* Open the index v2 B-tree, if it isn't already */ + if(NULL == bt2) { + if(NULL == (bt2 = H5B2_open(f, dxpl_id, header->index_addr, f))) + HGOTO_ERROR(H5E_SOHM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for SOHM index") + } /* end if */ + + if(H5B2_insert(bt2, dxpl_id, &key) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "couldn't add SOHM to B-tree") + } /* end else */ - ++(header->num_messages); - (*cache_flags_ptr) |= H5AC__DIRTIED_FLAG; + ++(header->num_messages); + (*cache_flags_ptr) |= H5AC__DIRTIED_FLAG; + } /* end if */ } /* end else */ /* Set the file pointer & message type for the shared component */ @@ -1395,7 +1447,7 @@ done: HDONE_ERROR(H5E_SOHM, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for SOHM index") /* If we got a list out of the cache, release it (it is always dirty after writing a message) */ - if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DIRTIED_FLAG) < 0) + if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, defer ? H5AC__NO_FLAGS_SET : H5AC__DIRTIED_FLAG) < 0) HDONE_ERROR(H5E_SOHM, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index") if(encoding_buf) |