From 8d40aa83cfa3cc2a062d30ffbc2eb423a3485985 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Tue, 17 Aug 2004 02:30:23 -0500 Subject: [svn-r9102] Purpose: Bug fix Description: 1 - Dataset contiguous storage cache information had a bug where it was possible to try to access invalid cache information if the cache wasn't filled the first time it attempted to loop through the list of offset/length vectors. 2 - Additionally, the contiguous storage cache information was being used in certain circumstances from the chunked dataset I/O code path, which was generally fatal since the chunk storage and contiguous storage information were stored together in a union. Solution: 1 - Avoid special case of first trip through loop over offset/length I/O vectors and always check for the contiguous storage sieve buffer buffer being NULL. 2 - Change the union containing the chunk and contiguous storage cache information into a struct, allowing both to be used at the same time. Platforms tested: FreeBSD 4.10 (sleipnir) h5committested --- src/H5D.c | 35 ++-- src/H5Dcontig.c | 530 ++++++++++++++++++++++++++------------------------------ src/H5Distore.c | 15 +- src/H5Dpkg.h | 6 +- 4 files changed, 278 insertions(+), 308 deletions(-) diff --git a/src/H5D.c b/src/H5D.c index 6121b43..273db9d 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -2705,14 +2705,16 @@ H5D_close(H5D_t *dataset) H5D_istore_stats(dataset, FALSE); #endif /* H5F_ISTORE_DEBUG */ + /* Free the data sieve buffer, if it's been allocated */ + if(dataset->cache.contig.sieve_buf) { + assert(dataset->layout.type!=H5D_COMPACT); /* We should never have a sieve buffer for compact storage */ + assert(dataset->cache.contig.sieve_dirty==0); /* The buffer had better be flushed... */ + dataset->cache.contig.sieve_buf = H5FL_BLK_FREE (sieve_buf,dataset->cache.contig.sieve_buf); + } /* end if */ + /* Free cached information for each kind of dataset */ switch(dataset->layout.type) { case H5D_CONTIGUOUS: - /* Free the data sieve buffer, if it's been allocated */ - if(dataset->cache.contig.sieve_buf) { - assert(dataset->cache.contig.sieve_dirty==0); /* The buffer had better be flushed... */ - dataset->cache.contig.sieve_buf = H5FL_BLK_FREE (sieve_buf,dataset->cache.contig.sieve_buf); - } /* end if */ break; case H5D_CHUNKED: @@ -3929,19 +3931,22 @@ H5D_flush(H5F_t *f, hid_t dxpl_id, unsigned flags) if(NULL==(dataset=H5I_object_verify(id_list[j], H5I_DATASET))) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to get dataset object") + /* flush the raw data buffer, if we have a dirty one */ + if (dataset->cache.contig.sieve_buf && dataset->cache.contig.sieve_dirty) { + assert(dataset->layout.type!=H5D_COMPACT); /* We should never have a sieve buffer for compact storage */ + + /* Write dirty data sieve buffer to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, dataset->cache.contig.sieve_loc, + dataset->cache.contig.sieve_size, dxpl_id, dataset->cache.contig.sieve_buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed") + + /* Reset sieve buffer dirty flag */ + dataset->cache.contig.sieve_dirty=0; + } /* end if */ + /* Flush cached information for each kind of dataset */ switch(dataset->layout.type) { case H5D_CONTIGUOUS: - /* flush the raw data buffer, if we have a dirty one */ - if (dataset->cache.contig.sieve_buf && dataset->cache.contig.sieve_dirty) { - /* Write dirty data sieve buffer to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, dataset->cache.contig.sieve_loc, - dataset->cache.contig.sieve_size, dxpl_id, dataset->cache.contig.sieve_buf) < 0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed") - - /* Reset sieve buffer dirty flag */ - dataset->cache.contig.sieve_dirty=0; - } /* end if */ break; case H5D_CHUNKED: diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index 7fa3ebd..32af4d8 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -406,10 +406,7 @@ H5D_contig_readvv(H5F_t *f, hid_t dxpl_id, H5D_t *dset, void *_buf) { unsigned char *buf=(unsigned char *)_buf; /* Pointer to buffer to fill */ - haddr_t abs_eoa; /* Absolute end of file address */ - haddr_t rel_eoa; /* Relative end of file address */ haddr_t addr; /* Actual address to read */ - hsize_t max_data; /* Actual maximum size of data to cache */ size_t size; /* Size of sequence in bytes */ size_t u; /* Counting variable */ size_t v; /* Counting variable */ @@ -427,82 +424,20 @@ H5D_contig_readvv(H5F_t *f, hid_t dxpl_id, H5D_t *dset, haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */ haddr_t contig_end; /* End locations of block to write */ size_t sieve_size; /* size of sieve buffer */ + haddr_t abs_eoa; /* Absolute end of file address */ + haddr_t rel_eoa; /* Relative end of file address */ + hsize_t max_data; /* Actual maximum size of data to cache */ /* Set offsets in sequence lists */ u=*dset_curr_seq; v=*mem_curr_seq; - /* No data sieve buffer yet, go allocate one */ - if(dset->cache.contig.sieve_buf==NULL) { - /* Choose smallest buffer to write */ - if(mem_len_arr[v]dset->cache.contig.sieve_buf_size) { - if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - } /* end if */ - else { - /* Allocate room for the data sieve buffer */ - if (NULL==(dset->cache.contig.sieve_buf=H5FL_BLK_MALLOC(sieve_buf,dset->cache.contig.sieve_buf_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - - /* Determine the new sieve buffer size & location */ - dset->cache.contig.sieve_loc=addr; - - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(f))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-H5F_get_base_addr(f); - - /* Compute the size of the sieve buffer */ - H5_ASSIGN_OVERFLOW(dset->cache.contig.sieve_size,MIN3(rel_eoa-dset->cache.contig.sieve_loc,max_data,dset->cache.contig.sieve_buf_size),hsize_t,size_t); - - /* Read the new sieve buffer */ - if (H5F_block_read(f, H5FD_MEM_DRAW, dset->cache.contig.sieve_loc, dset->cache.contig.sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(buf,dset->cache.contig.sieve_buf,size); - - /* Reset sieve buffer dirty flag */ - dset->cache.contig.sieve_dirty=0; - } /* end else */ - - /* Update memory information */ - mem_len_arr[v]-=size; - mem_offset_arr[v]+=size; - if(mem_len_arr[v]==0) - v++; - - /* Update file information */ - dset_len_arr[u]-=size; - dset_offset_arr[u]+=size; - if(dset_len_arr[u]==0) - u++; - - /* Increment number of bytes copied */ - ret_value+=size; - } /* end if */ - /* Stash local copies of these value */ - sieve_start=dset->cache.contig.sieve_loc; - sieve_size=dset->cache.contig.sieve_size; - sieve_end=sieve_start+sieve_size; + if(dset->cache.contig.sieve_buf!=NULL) { + sieve_start=dset->cache.contig.sieve_loc; + sieve_size=dset->cache.contig.sieve_size; + sieve_end=sieve_start+sieve_size; + } /* end if */ /* Works through sequences as fast as possible */ for(; u=sieve_start && contig_endcache.contig.sieve_buf+(addr-sieve_start); - - /* Grab the data out of the buffer */ - HDmemcpy(buf,base_sieve_buf,size); - } /* end if */ - /* Entire request is not within this data sieve buffer */ - else { + /* No data sieve buffer yet, go allocate one */ + if(dset->cache.contig.sieve_buf==NULL) { /* Check if we can actually hold the I/O request in the sieve buffer */ if(size>dset->cache.contig.sieve_buf_size) { - /* Check for any overlap with the current sieve buffer */ - if((sieve_start>=addr && sieve_start<(contig_end+1)) - || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { - /* Flush the sieve buffer, if it's dirty */ - if(dset->cache.contig.sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - dset->cache.contig.sieve_dirty=0; - } /* end if */ - } /* end if */ - - /* Read directly into the user's buffer */ if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); } /* end if */ - /* Element size fits within the buffer size */ else { - /* Flush the sieve buffer if it's dirty */ - if(dset->cache.contig.sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - dset->cache.contig.sieve_dirty=0; - } /* end if */ + /* Allocate room for the data sieve buffer */ + if (NULL==(dset->cache.contig.sieve_buf=H5FL_BLK_MALLOC(sieve_buf,dset->cache.contig.sieve_buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); /* Determine the new sieve buffer size & location */ dset->cache.contig.sieve_loc=addr; @@ -572,18 +475,12 @@ H5D_contig_readvv(H5F_t *f, hid_t dxpl_id, H5D_t *dset, /* Adjust absolute EOA address to relative EOA address */ rel_eoa=abs_eoa-H5F_get_base_addr(f); - /* Only need this when resizing sieve buffer */ + /* Set up the buffer parameters */ max_data=dset_size-dset_offset_arr[u]; /* Compute the size of the sieve buffer */ - /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ H5_ASSIGN_OVERFLOW(dset->cache.contig.sieve_size,MIN3(rel_eoa-dset->cache.contig.sieve_loc,max_data,dset->cache.contig.sieve_buf_size),hsize_t,size_t); - /* Update local copies of sieve information */ - sieve_start=dset->cache.contig.sieve_loc; - sieve_size=dset->cache.contig.sieve_size; - sieve_end=sieve_start+sieve_size; - /* Read the new sieve buffer */ if (H5F_block_read(f, H5FD_MEM_DRAW, dset->cache.contig.sieve_loc, dset->cache.contig.sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); @@ -593,6 +490,90 @@ H5D_contig_readvv(H5F_t *f, hid_t dxpl_id, H5D_t *dset, /* Reset sieve buffer dirty flag */ dset->cache.contig.sieve_dirty=0; + + /* Stash local copies of these value */ + sieve_start=dset->cache.contig.sieve_loc; + sieve_size=dset->cache.contig.sieve_size; + sieve_end=sieve_start+sieve_size; + } /* end else */ + } /* end if */ + else { + /* Compute end of sequence to retrieve */ + contig_end=addr+size-1; + + /* If entire read is within the sieve buffer, read it from the buffer */ + if(addr>=sieve_start && contig_endcache.contig.sieve_buf+(addr-sieve_start); + + /* Grab the data out of the buffer */ + HDmemcpy(buf,base_sieve_buf,size); + } /* end if */ + /* Entire request is not within this data sieve buffer */ + else { + /* Check if we can actually hold the I/O request in the sieve buffer */ + if(size>dset->cache.contig.sieve_buf_size) { + /* Check for any overlap with the current sieve buffer */ + if((sieve_start>=addr && sieve_start<(contig_end+1)) + || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { + /* Flush the sieve buffer, if it's dirty */ + if(dset->cache.contig.sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + dset->cache.contig.sieve_dirty=0; + } /* end if */ + } /* end if */ + + /* Read directly into the user's buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + } /* end if */ + /* Element size fits within the buffer size */ + else { + /* Flush the sieve buffer if it's dirty */ + if(dset->cache.contig.sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + dset->cache.contig.sieve_dirty=0; + } /* end if */ + + /* Determine the new sieve buffer size & location */ + dset->cache.contig.sieve_loc=addr; + + /* Make certain we don't read off the end of the file */ + if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(f))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); + + /* Adjust absolute EOA address to relative EOA address */ + rel_eoa=abs_eoa-H5F_get_base_addr(f); + + /* Only need this when resizing sieve buffer */ + max_data=dset_size-dset_offset_arr[u]; + + /* Compute the size of the sieve buffer */ + /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ + H5_ASSIGN_OVERFLOW(dset->cache.contig.sieve_size,MIN3(rel_eoa-dset->cache.contig.sieve_loc,max_data,dset->cache.contig.sieve_buf_size),hsize_t,size_t); + + /* Update local copies of sieve information */ + sieve_start=dset->cache.contig.sieve_loc; + sieve_size=dset->cache.contig.sieve_size; + sieve_end=sieve_start+sieve_size; + + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, dset->cache.contig.sieve_loc, dset->cache.contig.sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + + /* Grab the data out of the buffer (must be first piece of data in buffer ) */ + HDmemcpy(buf,dset->cache.contig.sieve_buf,size); + + /* Reset sieve buffer dirty flag */ + dset->cache.contig.sieve_dirty=0; + } /* end else */ } /* end else */ } /* end else */ @@ -685,10 +666,7 @@ H5D_contig_writevv(H5F_t *f, hid_t dxpl_id, H5D_t *dset, const void *_buf) { const unsigned char *buf=_buf; /* Pointer to buffer to fill */ - haddr_t abs_eoa; /* Absolute end of file address */ - haddr_t rel_eoa; /* Relative end of file address */ haddr_t addr; /* Actual address to read */ - hsize_t max_data; /* Actual maximum size of data to cache */ size_t size; /* Size of sequence in bytes */ size_t u; /* Counting variable */ size_t v; /* Counting variable */ @@ -706,13 +684,23 @@ H5D_contig_writevv(H5F_t *f, hid_t dxpl_id, H5D_t *dset, haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */ haddr_t contig_end; /* End locations of block to write */ size_t sieve_size; /* size of sieve buffer */ + haddr_t abs_eoa; /* Absolute end of file address */ + haddr_t rel_eoa; /* Relative end of file address */ + hsize_t max_data; /* Actual maximum size of data to cache */ /* Set offsets in sequence lists */ u=*dset_curr_seq; v=*mem_curr_seq; - /* No data sieve buffer yet, go allocate one */ - if(dset->cache.contig.sieve_buf==NULL) { + /* Stash local copies of these value */ + if(dset->cache.contig.sieve_buf!=NULL) { + sieve_start=dset->cache.contig.sieve_loc; + sieve_size=dset->cache.contig.sieve_size; + sieve_end=sieve_start+sieve_size; + } /* end if */ + + /* Works through sequences as fast as possible */ + for(; udset->cache.contig.sieve_buf_size) { - if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - } /* end if */ - else { - /* Allocate room for the data sieve buffer */ - if (NULL==(dset->cache.contig.sieve_buf=H5FL_BLK_MALLOC(sieve_buf,dset->cache.contig.sieve_buf_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - - /* Determine the new sieve buffer size & location */ - dset->cache.contig.sieve_loc=addr; - - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(f))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-H5F_get_base_addr(f); - - /* Compute the size of the sieve buffer */ - H5_ASSIGN_OVERFLOW(dset->cache.contig.sieve_size,MIN3(rel_eoa-dset->cache.contig.sieve_loc,max_data,dset->cache.contig.sieve_buf_size),hsize_t,size_t); - - /* Check if there is any point in reading the data from the file */ - if(dset->cache.contig.sieve_size>size) { - /* Read the new sieve buffer */ - if (H5F_block_read(f, H5FD_MEM_DRAW, dset->cache.contig.sieve_loc, dset->cache.contig.sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + /* No data sieve buffer yet, go allocate one */ + if(dset->cache.contig.sieve_buf==NULL) { + /* Check if we can actually hold the I/O request in the sieve buffer */ + if(size>dset->cache.contig.sieve_buf_size) { + if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); } /* end if */ + else { + /* Allocate room for the data sieve buffer */ + if (NULL==(dset->cache.contig.sieve_buf=H5FL_BLK_MALLOC(sieve_buf,dset->cache.contig.sieve_buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(dset->cache.contig.sieve_buf,buf,size); - - /* Set sieve buffer dirty flag */ - dset->cache.contig.sieve_dirty=1; - } /* end else */ - - /* Update memory information */ - mem_len_arr[v]-=size; - mem_offset_arr[v]+=size; - if(mem_len_arr[v]==0) - v++; - - /* Update file information */ - dset_len_arr[u]-=size; - dset_offset_arr[u]+=size; - if(dset_len_arr[u]==0) - u++; - - /* Increment number of bytes copied */ - ret_value+=size; - } /* end if */ + /* Determine the new sieve buffer size & location */ + dset->cache.contig.sieve_loc=addr; - /* Stash local copies of these value */ - sieve_start=dset->cache.contig.sieve_loc; - sieve_size=dset->cache.contig.sieve_size; - sieve_end=sieve_start+sieve_size; - - /* Works through sequences as fast as possible */ - for(; ucache.contig.sieve_size,MIN3(rel_eoa-dset->cache.contig.sieve_loc,max_data,dset->cache.contig.sieve_buf_size),hsize_t,size_t); - /* If entire write is within the sieve buffer, write it to the buffer */ - if(addr>=sieve_start && contig_endcache.contig.sieve_buf+(addr-sieve_start); + /* Check if there is any point in reading the data from the file */ + if(dset->cache.contig.sieve_size>size) { + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, dset->cache.contig.sieve_loc, dset->cache.contig.sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + } /* end if */ - /* Put the data into the sieve buffer */ - HDmemcpy(base_sieve_buf,buf,size); + /* Grab the data out of the buffer (must be first piece of data in buffer ) */ + HDmemcpy(dset->cache.contig.sieve_buf,buf,size); - /* Set sieve buffer dirty flag */ - dset->cache.contig.sieve_dirty=1; + /* Set sieve buffer dirty flag */ + dset->cache.contig.sieve_dirty=1; + /* Stash local copies of these value */ + sieve_start=dset->cache.contig.sieve_loc; + sieve_size=dset->cache.contig.sieve_size; + sieve_end=sieve_start+sieve_size; + } /* end else */ } /* end if */ - /* Entire request is not within this data sieve buffer */ else { - /* Check if we can actually hold the I/O request in the sieve buffer */ - if(size>dset->cache.contig.sieve_buf_size) { - /* Check for any overlap with the current sieve buffer */ - if((sieve_start>=addr && sieve_start<(contig_end+1)) - || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { - /* Flush the sieve buffer, if it's dirty */ - if(dset->cache.contig.sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + /* Compute end of sequence to retrieve */ + contig_end=addr+size-1; - /* Reset sieve buffer dirty flag */ - dset->cache.contig.sieve_dirty=0; - } /* end if */ + /* If entire write is within the sieve buffer, write it to the buffer */ + if(addr>=sieve_start && contig_endcache.contig.sieve_buf+(addr-sieve_start); - /* Force the sieve buffer to be re-read the next time */ - dset->cache.contig.sieve_loc=HADDR_UNDEF; - dset->cache.contig.sieve_size=0; - } /* end if */ + /* Put the data into the sieve buffer */ + HDmemcpy(base_sieve_buf,buf,size); + + /* Set sieve buffer dirty flag */ + dset->cache.contig.sieve_dirty=1; - /* Write directly from the user's buffer */ - if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); } /* end if */ - /* Element size fits within the buffer size */ + /* Entire request is not within this data sieve buffer */ else { - /* Check if it is possible to (exactly) prepend or append to existing (dirty) sieve buffer */ - if(((addr+size)==sieve_start || addr==sieve_end) && - (size+sieve_size)<=dset->cache.contig.sieve_buf_size && - dset->cache.contig.sieve_dirty) { - /* Prepend to existing sieve buffer */ - if((addr+size)==sieve_start) { - /* Move existing sieve information to correct location */ - HDmemmove(dset->cache.contig.sieve_buf+size,dset->cache.contig.sieve_buf,sieve_size); - - /* Copy in new information (must be first in sieve buffer) */ - HDmemcpy(dset->cache.contig.sieve_buf,buf,size); - - /* Adjust sieve location */ - dset->cache.contig.sieve_loc=addr; - + /* Check if we can actually hold the I/O request in the sieve buffer */ + if(size>dset->cache.contig.sieve_buf_size) { + /* Check for any overlap with the current sieve buffer */ + if((sieve_start>=addr && sieve_start<(contig_end+1)) + || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { + /* Flush the sieve buffer, if it's dirty */ + if(dset->cache.contig.sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + dset->cache.contig.sieve_dirty=0; + } /* end if */ + + /* Force the sieve buffer to be re-read the next time */ + dset->cache.contig.sieve_loc=HADDR_UNDEF; + dset->cache.contig.sieve_size=0; } /* end if */ - /* Append to existing sieve buffer */ - else { - /* Copy in new information */ - HDmemcpy(dset->cache.contig.sieve_buf+sieve_size,buf,size); - } /* end else */ - - /* Adjust sieve size */ - dset->cache.contig.sieve_size += size; - - /* Update local copies of sieve information */ - sieve_start=dset->cache.contig.sieve_loc; - sieve_size=dset->cache.contig.sieve_size; - sieve_end=sieve_start+sieve_size; + /* Write directly from the user's buffer */ + if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); } /* end if */ - /* Can't add the new data onto the existing sieve buffer */ + /* Element size fits within the buffer size */ else { - /* Flush the sieve buffer if it's dirty */ - if(dset->cache.contig.sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + /* Check if it is possible to (exactly) prepend or append to existing (dirty) sieve buffer */ + if(((addr+size)==sieve_start || addr==sieve_end) && + (size+sieve_size)<=dset->cache.contig.sieve_buf_size && + dset->cache.contig.sieve_dirty) { + /* Prepend to existing sieve buffer */ + if((addr+size)==sieve_start) { + /* Move existing sieve information to correct location */ + HDmemmove(dset->cache.contig.sieve_buf+size,dset->cache.contig.sieve_buf,sieve_size); + + /* Copy in new information (must be first in sieve buffer) */ + HDmemcpy(dset->cache.contig.sieve_buf,buf,size); + + /* Adjust sieve location */ + dset->cache.contig.sieve_loc=addr; + + } /* end if */ + /* Append to existing sieve buffer */ + else { + /* Copy in new information */ + HDmemcpy(dset->cache.contig.sieve_buf+sieve_size,buf,size); + } /* end else */ + + /* Adjust sieve size */ + dset->cache.contig.sieve_size += size; + + /* Update local copies of sieve information */ + sieve_start=dset->cache.contig.sieve_loc; + sieve_size=dset->cache.contig.sieve_size; + sieve_end=sieve_start+sieve_size; - /* Reset sieve buffer dirty flag */ - dset->cache.contig.sieve_dirty=0; } /* end if */ + /* Can't add the new data onto the existing sieve buffer */ + else { + /* Flush the sieve buffer if it's dirty */ + if(dset->cache.contig.sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - /* Determine the new sieve buffer size & location */ - dset->cache.contig.sieve_loc=addr; + /* Reset sieve buffer dirty flag */ + dset->cache.contig.sieve_dirty=0; + } /* end if */ - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(f))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); + /* Determine the new sieve buffer size & location */ + dset->cache.contig.sieve_loc=addr; - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-H5F_get_base_addr(f); + /* Make certain we don't read off the end of the file */ + if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(f))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - /* Only need this when resizing sieve buffer */ - max_data=dset_size-dset_offset_arr[u]; + /* Adjust absolute EOA address to relative EOA address */ + rel_eoa=abs_eoa-H5F_get_base_addr(f); - /* Compute the size of the sieve buffer */ - /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ - H5_ASSIGN_OVERFLOW(dset->cache.contig.sieve_size,MIN3(rel_eoa-dset->cache.contig.sieve_loc,max_data,dset->cache.contig.sieve_buf_size),hsize_t,size_t); + /* Only need this when resizing sieve buffer */ + max_data=dset_size-dset_offset_arr[u]; - /* Update local copies of sieve information */ - sieve_start=dset->cache.contig.sieve_loc; - sieve_size=dset->cache.contig.sieve_size; - sieve_end=sieve_start+sieve_size; + /* Compute the size of the sieve buffer */ + /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ + H5_ASSIGN_OVERFLOW(dset->cache.contig.sieve_size,MIN3(rel_eoa-dset->cache.contig.sieve_loc,max_data,dset->cache.contig.sieve_buf_size),hsize_t,size_t); - /* Check if there is any point in reading the data from the file */ - if(dset->cache.contig.sieve_size>size) { - /* Read the new sieve buffer */ - if (H5F_block_read(f, H5FD_MEM_DRAW, dset->cache.contig.sieve_loc, dset->cache.contig.sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - } /* end if */ + /* Update local copies of sieve information */ + sieve_start=dset->cache.contig.sieve_loc; + sieve_size=dset->cache.contig.sieve_size; + sieve_end=sieve_start+sieve_size; - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(dset->cache.contig.sieve_buf,buf,size); + /* Check if there is any point in reading the data from the file */ + if(dset->cache.contig.sieve_size>size) { + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, dset->cache.contig.sieve_loc, dset->cache.contig.sieve_size, dxpl_id, dset->cache.contig.sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + } /* end if */ - /* Set sieve buffer dirty flag */ - dset->cache.contig.sieve_dirty=1; + /* Grab the data out of the buffer (must be first piece of data in buffer ) */ + HDmemcpy(dset->cache.contig.sieve_buf,buf,size); + + /* Set sieve buffer dirty flag */ + dset->cache.contig.sieve_dirty=1; + } /* end else */ } /* end else */ } /* end else */ } /* end else */ diff --git a/src/H5Distore.c b/src/H5Distore.c index daa2582..cadda13 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -939,7 +939,6 @@ H5D_istore_init (H5F_t *f, H5D_t *dset) FUNC_ENTER_NOAPI(H5D_istore_init, FAIL); - HDmemset (rdcc, 0, sizeof(H5D_rdcc_t)); if (H5F_RDCC_NBYTES(f)>0 && H5F_RDCC_NELMTS(f)>0) { rdcc->nbytes=H5F_RDCC_NBYTES(f); rdcc->nslots = H5F_RDCC_NELMTS(f); @@ -1613,7 +1612,7 @@ else } assert (found || chunk_size>0); - if (!found && rdcc->nslots>0 && chunk_size<=dset->cache.chunk.nbytes && + if (!found && rdcc->nslots>0 && chunk_size<=rdcc->nbytes && (!ent || !ent->locked)) { /* * Add the chunk to the cache only if the slot is not already locked. @@ -1852,13 +1851,13 @@ H5D_istore_readvv(H5F_t *f, const struct H5D_dxpl_cache_t *dxpl_cache, hid_t dxp /* Get the address of this chunk on disk */ #ifdef QAK -HDfprintf(stderr,"%s: chunk_coords={",FUNC); +HDfprintf(stderr,"%s: store->chunk.offset={",FUNC); for(u=0; ulayout.u.chunk.ndims; u++) - HDfprintf(stderr,"%Hd%s",chunk_coords[u],(u<(dset->layout.u.chunk.ndims-1) ? ", " : "}\n")); + HDfprintf(stderr,"%Hd%s",store->chunk.offset[u],(u<(dset->layout.u.chunk.ndims-1) ? ", " : "}\n")); #endif /* QAK */ chunk_addr=H5D_istore_get_addr(f, dxpl_id, &(dset->layout), store->chunk.offset, &udata); #ifdef QAK -HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Hu\n",FUNC,chunk_addr,dset->layout.u.chunk.size); +HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Zu\n",FUNC,chunk_addr,dset->layout.u.chunk.size); HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]); HDfprintf(stderr,"%s: chunk_offset_arr[%Zu]=%Hu\n",FUNC,*chunk_curr_seq,chunk_offset_arr[*chunk_curr_seq]); HDfprintf(stderr,"%s: mem_len_arr[%Zu]=%Zu\n",FUNC,*mem_curr_seq,mem_len_arr[*mem_curr_seq]); @@ -1967,13 +1966,13 @@ H5D_istore_writevv(H5F_t *f, const struct H5D_dxpl_cache_t *dxpl_cache, /* Get the address of this chunk on disk */ #ifdef QAK -HDfprintf(stderr,"%s: chunk_coords={",FUNC); +HDfprintf(stderr,"%s: store->chunk.offset={",FUNC); for(u=0; ulayout.u.chunk.ndims; u++) - HDfprintf(stderr,"%Hd%s",chunk_coords[u],(u<(dset->layout.u.chunk.ndims-1) ? ", " : "}\n")); + HDfprintf(stderr,"%Hd%s",store->chunk.offset[u],(u<(dset->layout.u.chunk.ndims-1) ? ", " : "}\n")); #endif /* QAK */ chunk_addr=H5D_istore_get_addr(f, dxpl_id, &(dset->layout), store->chunk.offset, &udata); #ifdef QAK -HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Hu\n",FUNC,chunk_addr,dset->layout.u.chunk.size); +HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Zu\n",FUNC,chunk_addr,dset->layout.u.chunk.size); HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]); HDfprintf(stderr,"%s: chunk_offset_arr[%Zu]=%Hu\n",FUNC,*chunk_curr_seq,chunk_offset_arr[*chunk_curr_seq]); HDfprintf(stderr,"%s: mem_len_arr[%Zu]=%Zu\n",FUNC,*mem_curr_seq,mem_len_arr[*mem_curr_seq]); diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 30183c3..8b88e92 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -93,8 +93,12 @@ struct H5D_t { H5O_fill_t fill; /* Dataset fill value information */ /* Buffered/cached information for types of raw data storage*/ - union { + struct { H5D_rdcdc_t contig; /* Information about contiguous data */ + /* (Note that the "contig" cache + * information can be used by a chunked + * dataset in certain circumstances) + */ H5D_rdcc_t chunk; /* Information about chunked data */ }cache; }; -- cgit v0.12