diff options
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) |