diff options
author | Vailin Choi <vchoi@hdfgroup.org> | 2013-06-26 20:35:42 (GMT) |
---|---|---|
committer | Vailin Choi <vchoi@hdfgroup.org> | 2013-06-26 20:35:42 (GMT) |
commit | 5845fed5cb1dad347d71ccd2a7c9091ffaccff0a (patch) | |
tree | 796fe4a86905b9dd8a8cc7d8e1990a6ce26378b7 /src/H5Ocache.c | |
parent | d9517c14af7bc68bd093b14eb8eeaab87d1ea80e (diff) | |
download | hdf5-5845fed5cb1dad347d71ccd2a7c9091ffaccff0a.zip hdf5-5845fed5cb1dad347d71ccd2a7c9091ffaccff0a.tar.gz hdf5-5845fed5cb1dad347d71ccd2a7c9091ffaccff0a.tar.bz2 |
[svn-r23828] Fix 2 bugs for SWMR access:
1) H5O_load() in H5Ocache.c: when reading a block that is > spec_read siez, read the whole block in again and possibly decode the header.
2) H5F_accum_write() in H5Faccum.c: for a large write that is >= H5F_ACCUM_MAX_SIZE, flush the metadata in the accumulator first before the write.
Tests are added to test/ohdr.c and test/accum.c. h5committested.
Diffstat (limited to 'src/H5Ocache.c')
-rw-r--r-- | src/H5Ocache.c | 196 |
1 files changed, 126 insertions, 70 deletions
diff --git a/src/H5Ocache.c b/src/H5Ocache.c index 856a5bc..80f5c05 100644 --- a/src/H5Ocache.c +++ b/src/H5Ocache.c @@ -93,6 +93,8 @@ static herr_t H5O_chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno); static herr_t H5O_add_cont_msg(H5O_cont_msgs_t *cont_msg_info, const H5O_cont_t *cont); +static herr_t H5O_decode_prefix(H5F_t *f, H5O_t *oh, const uint8_t *buf, void *_udata); + /*********************/ /* Package Variables */ @@ -139,76 +141,34 @@ H5FL_SEQ_DEFINE(H5O_cont_t); /* Local Variables */ /*******************/ - /*------------------------------------------------------------------------- - * Function: H5O_load + * Function: H5O_decode_prefix * - * Purpose: Loads an object header from disk. + * Purpose: To decode the object header prefix. + * The coding is extracted fromt H5O_load() to this routine. * - * Return: Success: Pointer to the new object header. + * Return: Non-negative on success/Negative on failure * - * Failure: NULL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 5 1997 + * Programmer: Vailin Choi; June 2013 * *------------------------------------------------------------------------- */ -static H5O_t * -H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) +static herr_t +H5O_decode_prefix(H5F_t *f, H5O_t *oh, const uint8_t *buf, void *_udata) { - H5O_t *oh = NULL; /* Object header read in */ H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */ - H5WB_t *wb = NULL; /* Wrapped buffer for prefix data */ - uint8_t read_buf[H5O_SPEC_READ_SIZE]; /* Buffer for speculative read */ - const uint8_t *p; /* Pointer into buffer to decode */ - uint8_t *buf; /* Buffer to decode */ - size_t spec_read_size; /* Size of buffer to speculatively read in */ - size_t prefix_size; /* Size of object header prefix */ - size_t buf_size; /* Size of prefix+chunk #0 buffer */ - haddr_t eoa; /* Relative end of file address */ - H5O_t *ret_value; /* Return value */ + const uint8_t *p = buf; /* Pointer into buffer to decode */ + size_t prefix_size; /* Size of object header prefix */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check arguments */ HDassert(f); - HDassert(H5F_addr_defined(addr)); + HDassert(oh); + HDassert(buf); HDassert(udata); - HDassert(udata->common.f); - HDassert(udata->common.cont_msg_info); - - /* Make certain we don't speculatively read off the end of the file */ - if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_OHDR))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine file size") - - /* Compute the size of the speculative object header buffer */ - H5_ASSIGN_OVERFLOW(spec_read_size, MIN(eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t); - - /* Attempt to speculatively read both object header prefix and first chunk */ - if(H5F_block_read(f, H5FD_MEM_OHDR, addr, spec_read_size, dxpl_id, read_buf) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header") - p = read_buf; - - /* Allocate space for the object header data structure */ - if(NULL == (oh = H5FL_CALLOC(H5O_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - - /* File-specific, non-stored information */ - oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f); - oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f); - oh->swmr_write = !!(H5F_INTENT(udata->common.f) & H5F_ACC_SWMR_WRITE); - - /* Create object header proxy if doing SWMR writes */ - HDassert(!oh->proxy_present); - if(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) { - if(H5O_proxy_create(f, dxpl_id, oh) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, NULL, "can't create object header proxy") - } /* end if */ - else - oh->proxy_addr = HADDR_UNDEF; /* Check for presence of magic number */ /* (indicates version 2 or later) */ @@ -219,12 +179,12 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) /* Version */ oh->version = *p++; if(H5O_VERSION_2 != oh->version) - HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number") + HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number") /* Flags */ oh->flags = *p++; if(oh->flags & ~H5O_HDR_ALL_FLAGS) - HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "unknown object header status flag(s)") + HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown object header status flag(s)") /* Number of links to object (unless overridden by refcount message) */ oh->nlink = 1; @@ -250,7 +210,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) UINT16DECODE(p, oh->max_compact); UINT16DECODE(p, oh->min_dense); if(oh->max_compact < oh->min_dense) - HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header attribute phase change values") + HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header attribute phase change values") } /* end if */ else { oh->max_compact = H5O_CRT_ATTR_MAX_COMPACT_DEF; @@ -276,16 +236,16 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) break; default: - HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad size for chunk 0") + HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0") } /* end switch */ if(oh->chunk0_size > 0 && oh->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) - HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header chunk size") + HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size") } /* end if */ else { /* Version */ oh->version = *p++; if(H5O_VERSION_1 != oh->version) - HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number") + HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number") /* Flags */ oh->flags = H5O_CRT_OHDR_FLAGS_DEF; @@ -310,16 +270,100 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) UINT32DECODE(p, oh->chunk0_size); if((udata->v1_pfx_nmesgs > 0 && oh->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) || (udata->v1_pfx_nmesgs == 0 && oh->chunk0_size > 0)) - HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "bad object header chunk size") + HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size") /* Reserved, in version 1 (for 8-byte alignment padding) */ p += 4; } /* end else */ /* Determine object header prefix length */ - prefix_size = (size_t)(p - (const uint8_t *)read_buf); + prefix_size = (size_t)(p - buf); HDassert((size_t)prefix_size == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh))); +done: + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5O_decode_prefix() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_load + * + * Purpose: Loads an object header from disk. + * + * Return: Success: Pointer to the new object header. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 5 1997 + * + * Modifications: + * Vailin Choi; June 2013 + * This is a fix for SWMR: + * When reading a block that is > spec_read_size, read the whole block in + * again and possibly decode the header. + * Move the coding for decoding the object header prefix to another routine + * H5O_decode_prefix(). + *------------------------------------------------------------------------- + */ +static H5O_t * +H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) +{ + H5O_t *oh = NULL; /* Object header read in */ + H5O_cache_ud_t *udata = (H5O_cache_ud_t *)_udata; /* User data for callback */ + H5WB_t *wb = NULL; /* Wrapped buffer for prefix data */ + uint8_t read_buf[H5O_SPEC_READ_SIZE]; /* Buffer for speculative read */ + const uint8_t *p; /* Pointer into buffer to decode */ + uint8_t *buf; /* Buffer to decode */ + size_t spec_read_size; /* Size of buffer to speculatively read in */ + size_t buf_size; /* Size of prefix+chunk #0 buffer */ + haddr_t eoa; /* Relative end of file address */ + H5O_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(udata); + HDassert(udata->common.f); + HDassert(udata->common.cont_msg_info); + + /* Make certain we don't speculatively read off the end of the file */ + if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_OHDR))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine file size") + + /* Compute the size of the speculative object header buffer */ + H5_ASSIGN_OVERFLOW(spec_read_size, MIN(eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t); + + /* Attempt to speculatively read both object header prefix and first chunk */ + if(H5F_block_read(f, H5FD_MEM_OHDR, addr, spec_read_size, dxpl_id, read_buf) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header") + p = read_buf; + + /* Allocate space for the object header data structure */ + if(NULL == (oh = H5FL_CALLOC(H5O_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* File-specific, non-stored information */ + oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f); + oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f); + oh->swmr_write = !!(H5F_INTENT(udata->common.f) & H5F_ACC_SWMR_WRITE); + + /* Create object header proxy if doing SWMR writes */ + HDassert(!oh->proxy_present); + if(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) { + if(H5O_proxy_create(f, dxpl_id, oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, NULL, "can't create object header proxy") + } /* end if */ + else + oh->proxy_addr = HADDR_UNDEF; + + if(H5O_decode_prefix(f, oh, read_buf, udata) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't decode object header prefix") + /* Compute the size of the buffer used */ buf_size = oh->chunk0_size + (size_t)H5O_SIZEOF_HDR(oh); @@ -333,14 +377,26 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) if(NULL == (buf = (uint8_t *)H5WB_actual(wb, buf_size))) HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't get actual buffer") - /* Copy existing raw data into new buffer */ - HDmemcpy(buf, read_buf, spec_read_size); - - /* Read rest of the raw data */ - if(H5F_block_read(f, H5FD_MEM_OHDR, (addr + spec_read_size), (buf_size - spec_read_size), dxpl_id, (buf + spec_read_size)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data") - } /* end if */ - else + /* SWMR access */ + if(H5F_INTENT(f) & H5F_ACC_SWMR_READ || H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) { + /* Read the chunk that is bigger than the speculative read size */ + if(H5F_block_read(f, H5FD_MEM_OHDR, addr, buf_size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header") + /* See if the data read now is the same as what is read initially */ + if(HDmemcmp(buf, read_buf, spec_read_size)) { + HDmemset(oh, 0, sizeof(oh)); + if(H5O_decode_prefix(f, oh, buf, udata) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't decode object header prefix") + } + } else { + /* Copy existing raw data into new buffer */ + HDmemcpy(buf, read_buf, spec_read_size); + + /* Read rest of the raw data */ + if(H5F_block_read(f, H5FD_MEM_OHDR, (addr + spec_read_size), (buf_size - spec_read_size), dxpl_id, (buf + spec_read_size)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data") + } + } else buf = read_buf; /* Parse the first chunk */ |