From 39220e7a3055735e4dfced3a3b4d07c91c386447 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 13 Oct 2005 15:19:28 -0500 Subject: [svn-r11557] Purpose: Bug fix Description: Mark continuation message & chunk as dirty for case where chunk is extended. Also refactored code to reduce duplication. Platforms tested: FreeBSD 4.11 (sleipnir) Linux 2.4 Too minor to require h5committest --- src/H5O.c | 338 ++++++++++++++++++-------------------------------------------- 1 file changed, 97 insertions(+), 241 deletions(-) diff --git a/src/H5O.c b/src/H5O.c index 81da26f..2a3f39c 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -2858,8 +2858,6 @@ done: * * Programmer: John Mainzer -- 8/16/05 * - * Modifications: - * *------------------------------------------------------------------------- */ static htri_t @@ -2869,272 +2867,130 @@ H5O_alloc_extend_chunk(H5F_t *f, size_t size, unsigned * msg_idx) { - unsigned u; - unsigned idx; - unsigned i; - size_t delta, old_size; + size_t delta; /* Change in chunk's size */ size_t aligned_size = H5O_ALIGN(size); - uint8_t *old_addr; - herr_t result; - htri_t tri_result; - htri_t ret_value; /* return value */ - hbool_t cont_updated; + uint8_t *old_image; /* Old address of chunk's image in memory */ + size_t old_size; /* Old size of chunk */ + htri_t tri_result; /* Result from checking if chunk can be extended */ + int extend_msg = -1;/* Index of null message to extend */ + unsigned u; /* Local index variable */ + htri_t ret_value = TRUE; /* return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_alloc_extend_chunk); + FUNC_ENTER_NOAPI_NOINIT(H5O_alloc_extend_chunk) /* check args */ - HDassert( f != NULL ); - HDassert( oh != NULL ); - HDassert( chunkno < oh->nchunks ); - HDassert( size > 0 ); - HDassert( msg_idx != NULL ); - - if ( !H5F_addr_defined(oh->chunk[chunkno].addr) ) { + HDassert(f != NULL); + HDassert(oh != NULL); + HDassert(chunkno < oh->nchunks); + HDassert(size > 0); + HDassert(msg_idx != NULL); - HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "chunk isn't on disk"); - } + if(!H5F_addr_defined(oh->chunk[chunkno].addr)) + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "chunk isn't on disk") - /* Test to see if the specified chunk ends with a null messages. If - * it does, try to extend the chunk and (thereby) the null message. - * If successful, return the index of the the null message in *msg_idx. + /* Test to see if the specified chunk ends with a null messages. + * If successful, set the index of the the null message in extend_msg. */ - for ( idx = 0; idx < oh->nmesgs; idx++ ) - { - if (oh->mesg[idx].chunkno==chunkno) { - - if (H5O_NULL_ID == oh->mesg[idx].type->id && - (oh->mesg[idx].raw + oh->mesg[idx].raw_size == - oh->chunk[chunkno].image + oh->chunk[chunkno].size)) { - - delta = MAX(H5O_MIN_SIZE, - aligned_size - oh->mesg[idx].raw_size); - - HDassert( delta == H5O_ALIGN(delta) ); - - /* determine whether the chunk can be extended */ - tri_result = H5MF_can_extend(f, H5FD_MEM_OHDR, - oh->chunk[chunkno].addr, - (hsize_t)(oh->chunk[chunkno].size), - (hsize_t)delta); - - if ( tri_result == FALSE ) { /* can't extend -- we are done */ - - HGOTO_DONE(FALSE); - - } else if ( tri_result != TRUE ) { /* system error */ - - HGOTO_ERROR (H5E_RESOURCE, H5E_SYSTEM, FAIL, \ - "H5MF_can_extend() failed"); - } - - /* if we get this far, we should be able to extend the chunk */ - result = H5MF_extend(f, H5FD_MEM_OHDR, - oh->chunk[chunkno].addr, - (hsize_t)(oh->chunk[chunkno].size), - (hsize_t)delta); - - if ( result < 0 ) { /* system error */ - - HGOTO_ERROR (H5E_RESOURCE, H5E_SYSTEM, FAIL, \ - "H5MF_extend() failed."); - } - - - /* chunk size has been increased -- tidy up */ - - oh->mesg[idx].dirty = TRUE; - oh->mesg[idx].raw_size += delta; - - old_addr = oh->chunk[chunkno].image; - - /* Be careful not to indroduce garbage */ - oh->chunk[chunkno].image = - H5FL_BLK_REALLOC(chunk_image,old_addr, - (oh->chunk[chunkno].size + delta)); - - if ( NULL == oh->chunk[chunkno].image ) { + for(u = 0; u < oh->nmesgs; u++) { + /* Check for null message at end of proper chunk */ + if(oh->mesg[u].chunkno == chunkno && H5O_NULL_ID == oh->mesg[u].type->id && + (oh->mesg[u].raw + oh->mesg[u].raw_size == oh->chunk[chunkno].image + oh->chunk[chunkno].size)) { - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, \ - "memory allocation failed"); - } - - HDmemset(oh->chunk[chunkno].image + oh->chunk[chunkno].size, - 0, delta); - - oh->chunk[chunkno].size += delta; - - /* adjust raw addresses for messages of this chunk */ - if (old_addr != oh->chunk[chunkno].image) { - for (u = 0; u < oh->nmesgs; u++) { - if (oh->mesg[u].chunkno == chunkno) - oh->mesg[u].raw = oh->chunk[chunkno].image + - (oh->mesg[u].raw - old_addr); - } - } - - /* adjust the continuation message pointing to this chunk - * for the increase in chunk size. - * - * As best I understand the code, it is not necessarily an - * error if there is no continuation message pointing to a - * chunk -- for example, chunk 0 seems to be pointed to by - * the object header. - */ - cont_updated = FALSE; - for ( i = 0; i < oh->nmesgs; i++ ) - { - if ( ( H5O_CONT_ID == oh->mesg[i].type->id ) && - ( ((H5O_cont_t *)(oh->mesg[i].native))->chunkno - == chunkno ) ) { - - HDassert( ((H5O_cont_t *)(oh->mesg[i].native))->size - == oh->chunk[chunkno].size - delta ); - - ((H5O_cont_t *)(oh->mesg[i].native))->size = - oh->chunk[chunkno].size; - - cont_updated = TRUE; - - /* there should be at most one continuation message - * pointing to this chunk, so we can quit when we find - * and update it. - */ - break; - } - } - HDassert( ( chunkno == 0 ) || ( cont_updated ) ); - - *msg_idx = idx; - HGOTO_DONE(TRUE); - } + extend_msg = u; + break; } /* end if */ } /* end for */ - /* if we get this far, the specified chunk does not end in a null message. - * Attempt to extend the chunk, and if successful, fill the new section - * of the chunk with a null messages. - */ - - /* compute space needed in the file */ - delta = MAX(H5O_MIN_SIZE, aligned_size+H5O_SIZEOF_MSGHDR(f)); + /* If we can extend an existing null message, adjust the delta appropriately */ + if(extend_msg >= 0) + delta = MAX(H5O_MIN_SIZE, aligned_size - oh->mesg[extend_msg].raw_size); + else + delta = MAX(H5O_MIN_SIZE, aligned_size + H5O_SIZEOF_MSGHDR(f)); delta = H5O_ALIGN(delta); /* determine whether the chunk can be extended */ - tri_result = H5MF_can_extend(f, H5FD_MEM_OHDR, - oh->chunk[chunkno].addr, - (hsize_t)(oh->chunk[chunkno].size), - (hsize_t)delta); - - if ( tri_result == FALSE ) { /* can't extend -- we are done */ - + tri_result = H5MF_can_extend(f, H5FD_MEM_OHDR, oh->chunk[chunkno].addr, + (hsize_t)(oh->chunk[chunkno].size), (hsize_t)delta); + if(tri_result == FALSE) { /* can't extend -- we are done */ HGOTO_DONE(FALSE); - - } else if ( tri_result != TRUE ) { /* system error */ - - HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, "H5MF_can_extend() failed"); - } - - /* if we get this far, we should be able to extend the chunk */ - result = H5MF_extend(f, H5FD_MEM_OHDR, - oh->chunk[chunkno].addr, - (hsize_t)(oh->chunk[chunkno].size), - (hsize_t)delta); - - if ( result < 0 ) { /* system error */ - - HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, \ - "H5MF_extend() failed"); + } else if(tri_result != TRUE) { /* system error */ + HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, "can't tell if we can extend chunk") } + /* If we get this far, we should be able to extend the chunk */ + if(H5MF_extend(f, H5FD_MEM_OHDR, oh->chunk[chunkno].addr, (hsize_t)(oh->chunk[chunkno].size), (hsize_t)delta) < 0 ) + HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, "can't extend chunk") - /* create a new null message */ - if ( oh->nmesgs >= oh->alloc_nmesgs ) { - - unsigned na = oh->alloc_nmesgs + H5O_NMESGS; - - H5O_mesg_t *x = H5FL_SEQ_REALLOC (H5O_mesg_t, oh->mesg, (size_t)na); - - if ( NULL == x ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ - "memory allocation failed"); - } - oh->alloc_nmesgs = na; - oh->mesg = x; - } + /* If we can extend an existing null message, take take of that */ + if(extend_msg >= 0) { + /* Adjust message size of existing null message */ + oh->mesg[extend_msg].dirty = TRUE; + oh->mesg[extend_msg].raw_size += delta; + } /* end if */ + /* Create new null message for end of chunk */ + else { + /* Create a new null message */ + if(oh->nmesgs >= oh->alloc_nmesgs) { + unsigned na = oh->alloc_nmesgs + H5O_NMESGS; + H5O_mesg_t *x = H5FL_SEQ_REALLOC(H5O_mesg_t, oh->mesg, (size_t)na); - idx = oh->nmesgs++; + if(NULL == x) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + oh->alloc_nmesgs = na; + oh->mesg = x; + } /* end if */ - oh->mesg[idx].type = H5O_NULL; - oh->mesg[idx].dirty = TRUE; - oh->mesg[idx].native = NULL; - oh->mesg[idx].raw = oh->chunk[chunkno].image + - oh->chunk[chunkno].size + - H5O_SIZEOF_MSGHDR(f); - oh->mesg[idx].raw_size = delta - H5O_SIZEOF_MSGHDR(f); - oh->mesg[idx].chunkno = chunkno; + /* Set extension message */ + extend_msg = oh->nmesgs++; + + /* Initialize new null message */ + oh->mesg[extend_msg].type = H5O_NULL; + oh->mesg[extend_msg].dirty = TRUE; + oh->mesg[extend_msg].native = NULL; + oh->mesg[extend_msg].raw = oh->chunk[chunkno].image + + oh->chunk[chunkno].size + H5O_SIZEOF_MSGHDR(f); + oh->mesg[extend_msg].raw_size = delta - H5O_SIZEOF_MSGHDR(f); + oh->mesg[extend_msg].chunkno = chunkno; + } /* end else */ - old_addr = oh->chunk[chunkno].image; + /* Allocate more memory space for chunk's image */ + old_image = oh->chunk[chunkno].image; old_size = oh->chunk[chunkno].size; oh->chunk[chunkno].size += delta; - oh->chunk[chunkno].image = H5FL_BLK_REALLOC(chunk_image,old_addr, - oh->chunk[chunkno].size); - if (NULL==oh->chunk[chunkno].image) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, \ - "memory allocation failed"); - } - - HDmemset(oh->chunk[chunkno].image+old_size, 0, - oh->chunk[chunkno].size - old_size); - - /* adjust raw addresses for messages of this chunk */ - if (old_addr != oh->chunk[chunkno].image) { - for (u = 0; u < oh->nmesgs; u++) { - if (oh->mesg[u].chunkno == chunkno) - oh->mesg[u].raw = oh->chunk[chunkno].image + - (oh->mesg[u].raw - old_addr); - } - } - - /* adjust the continuation message pointing to this chunk for the - * increase in chunk size. - * - * As best I understand the code, it is not necessarily an error - * if there is no continuation message pointing to a chunk -- for - * example, chunk 0 seems to be pointed to by the object header. - */ - cont_updated = FALSE; - for ( i = 0; i < oh->nmesgs; i++ ) - { - if ( ( H5O_CONT_ID == oh->mesg[i].type->id ) && - ( ((H5O_cont_t *)(oh->mesg[i].native))->chunkno == chunkno ) ) { - - HDassert( ((H5O_cont_t *)(oh->mesg[i].native))->size == - oh->chunk[chunkno].size - delta ); - - ((H5O_cont_t *)(oh->mesg[i].native))->size = - oh->chunk[chunkno].size; - - cont_updated = TRUE; - - /* there should be at most one continuation message - * pointing to this chunk, so we can quit when we find - * and update it. - */ - break; - } - } - HDassert( ( chunkno == 0 ) || ( cont_updated ) ); + oh->chunk[chunkno].image = H5FL_BLK_REALLOC(chunk_image, old_image, oh->chunk[chunkno].size); + oh->chunk[chunkno].dirty = TRUE; + if(NULL == oh->chunk[chunkno].image) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Wipe new space for chunk */ + HDmemset(oh->chunk[chunkno].image + old_size, 0, oh->chunk[chunkno].size - old_size); + + /* Spin through existing messages, adjusting them */ + for(u = 0; u < oh->nmesgs; u++) { + /* Adjust raw addresses for messages in this chunk to reflect to 'image' address */ + if(oh->mesg[u].chunkno == chunkno) + oh->mesg[u].raw = oh->chunk[chunkno].image + (oh->mesg[u].raw - old_image); + + /* Find continuation message which points to this chunk and adjust chunk's size */ + /* (Chunk 0 doesn't have a continuation message that points to it and + * it's size is directly encoded in the object header) */ + if(chunkno > 0 && (H5O_CONT_ID == oh->mesg[u].type->id) && + (((H5O_cont_t *)(oh->mesg[u].native))->chunkno == chunkno)) { + /* Adjust size of continuation message */ + HDassert(((H5O_cont_t *)(oh->mesg[u].native))->size == old_size); + ((H5O_cont_t *)(oh->mesg[u].native))->size = oh->chunk[chunkno].size; + + /* Flag continuation message & it's chunk as dirty */ + oh->mesg[u].dirty = TRUE; + oh->chunk[oh->mesg[u].chunkno].dirty = TRUE; + } /* end if */ + } /* end for */ /* Set return value */ - *msg_idx = idx; - ret_value = TRUE; + *msg_idx = extend_msg; done: - - FUNC_LEAVE_NOAPI(ret_value); - + FUNC_LEAVE_NOAPI(ret_value) } /* H5O_alloc_extend_chunk() */ -- cgit v0.12