diff options
Diffstat (limited to 'src/H5Dcontig.c')
-rw-r--r-- | src/H5Dcontig.c | 1271 |
1 files changed, 497 insertions, 774 deletions
diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index 2593d83..3a14175 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -18,9 +18,8 @@ * * Purpose: * Contiguous dataset I/O functions. These routines are similar to - * the H5F_istore_* routines and really only abstract away dealing - * with the data sieve buffer from the H5F_arr_read/write and - * H5F_seg_read/write. + * the H5F_istore_* routines and really only an abstract way of dealing + * with the data sieve buffer from H5F_seg_read/write. */ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ @@ -34,6 +33,7 @@ #include "H5MFprivate.h" /*file memory management */ #include "H5Oprivate.h" /* Object headers */ #include "H5Pprivate.h" /* Property lists */ +#include "H5Sprivate.h" /* Dataspace functions */ #include "H5Vprivate.h" /* Vector and array functions */ /* MPIO, MPIPOSIX, & FPHDF5 drivers needed for special checks */ @@ -41,6 +41,11 @@ #include "H5FDmpio.h" #include "H5FDmpiposix.h" +/* Private prototypes */ +static herr_t +H5F_contig_write(H5F_t *f, hsize_t max_data, haddr_t addr, + const size_t size, hid_t dxpl_id, const void *buf); + /* Interface initialization */ #define PABLO_MASK H5Fcontig_mask static int interface_initialize_g = 0; @@ -57,6 +62,48 @@ H5FL_BLK_DEFINE_STATIC(zero_fill); /*------------------------------------------------------------------------- + * Function: H5F_contig_create + * + * Purpose: Allocate file space for a contiguously stored dataset + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * April 19, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_contig_create(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout) +{ + hsize_t size; /* Size of contiguous block of data */ + unsigned u; /* Local index variable */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_contig_create, FAIL); + + /* check args */ + assert(f); + assert(layout); + + /* Compute size */ + size=layout->dim[0]; + for (u = 1; u < layout->ndims; u++) + size *= layout->dim[u]; + assert (size>0); + + /* Allocate space for the contiguous data */ + if (HADDR_UNDEF==(layout->addr=H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, size))) + HGOTO_ERROR (H5E_IO, H5E_NOSPACE, FAIL, "unable to reserve file space"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5F_contig_create */ + + +/*------------------------------------------------------------------------- * Function: H5F_contig_fill * * Purpose: Write fill values to a contiguously stored dataset. @@ -75,8 +122,7 @@ H5FL_BLK_DEFINE_STATIC(zero_fill); */ herr_t H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, - const struct H5S_t *space, + struct H5P_genplist_t *dc_plist, const struct H5S_t *space, const struct H5O_fill_t *fill, size_t elmt_size) { hssize_t snpoints; /* Number of points in space (for error checking) */ @@ -84,7 +130,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, size_t ptsperbuf; /* Maximum # of points which fit in the buffer */ size_t bufsize=64*1024; /* Size of buffer to write */ size_t size; /* Current # of points to write */ - hsize_t addr; /* Offset in dataset */ + haddr_t addr; /* Offset of dataset */ void *buf = NULL; /* Buffer for fill value writing */ #ifdef H5_HAVE_PARALLEL MPI_Comm mpi_comm=MPI_COMM_NULL; /* MPI communicator for file */ @@ -173,8 +219,8 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, * this quite efficiently by making sure we copy the fill value * in relatively large pieces. */ - ptsperbuf = MAX(1, bufsize/elmt_size); - bufsize = ptsperbuf*elmt_size; + ptsperbuf = MAX(1, bufsize/elmt_size); + bufsize = ptsperbuf*elmt_size; /* Fill the buffer with the user's fill value */ if(fill->buf) { @@ -207,7 +253,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, } /* end else */ /* Start at the beginning of the dataset */ - addr = 0; + addr = layout->addr; /* Loop through writing the fill value to the dataset */ while (npoints>0) { @@ -218,8 +264,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, if(using_mpi) { /* Round-robin write the chunks out from only one process */ if(mpi_round==mpi_rank) { - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space, - elmt_size, size, addr, buf)<0) + if (H5F_contig_write(f, size, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset"); } /* end if */ ++mpi_round; @@ -230,8 +275,8 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, } /* end if */ else { #endif /* H5_HAVE_PARALLEL */ - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space, - elmt_size, size, addr, buf)<0) + H5_CHECK_OVERFLOW(size,size_t,hsize_t); + if (H5F_contig_write(f, (hsize_t)size, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset"); #ifdef H5_HAVE_PARALLEL } /* end else */ @@ -314,44 +359,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_contig_read - * - * Purpose: Reads some data from a dataset into a buffer. - * The data is contiguous. The address is relative to the base - * address for the file. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Thursday, September 28, 2000 - * - * Modifications: - * Re-written in terms of the new readv call, QAK, 7/7/01 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_contig_read(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr, - size_t size, hid_t dxpl_id, void *buf/*out*/) -{ - hsize_t offset=0; /* Offset for vector call */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_contig_read, FAIL); - - /* Check args */ - assert(f); - assert(buf); - - if (H5F_contig_readv(f, max_data, type, addr, 1, &size, &offset, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vector read failed"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_contig_read() */ - - -/*------------------------------------------------------------------------- * Function: H5F_contig_write * * Purpose: Writes some data from a dataset into a buffer. @@ -364,23 +371,28 @@ done: * Thursday, September 28, 2000 * * Modifications: - * Re-written in terms of the new readv call, QAK, 7/7/01 + * Re-written in terms of the new writevv call, QAK, 5/7/03 * *------------------------------------------------------------------------- */ -herr_t -H5F_contig_write(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr, size_t size, - hid_t dxpl_id, const void *buf) +static herr_t +H5F_contig_write(H5F_t *f, hsize_t max_data, haddr_t addr, + const size_t size, hid_t dxpl_id, const void *buf) { - hsize_t offset=0; /* Offset for vector call */ - herr_t ret_value=SUCCEED; /* Return value */ + hsize_t dset_off=0; /* Offset in dataset */ + hsize_t mem_off=0; /* Offset in memory */ + size_t dset_len=size; /* Length in dataset */ + size_t mem_len=size; /* Length in memory */ + size_t mem_curr_seq=0; /* "Current sequence" in memory */ + size_t dset_curr_seq=0; /* "Current sequence" in dataset */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_contig_write, FAIL); assert (f); assert (buf); - if (H5F_contig_writev(f, max_data, type, addr, 1, &size, &offset, dxpl_id, buf)<0) + if (H5F_contig_writevv(f, max_data, addr, 1, &dset_curr_seq, &dset_len, &dset_off, 1, &mem_curr_seq, &mem_len, &mem_off, dxpl_id, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed"); done: @@ -389,7 +401,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_contig_readv + * Function: H5F_contig_readvv * * Purpose: Reads some data vectors from a dataset into a buffer. * The data is contiguous. The address is the start of the dataset, @@ -409,9 +421,10 @@ done: *------------------------------------------------------------------------- */ herr_t -H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, - size_t nseq, size_t size_arr[], hsize_t offset_arr[], hid_t dxpl_id, - void *_buf/*out*/) +H5F_contig_readvv(H5F_t *f, hsize_t _max_data, haddr_t _addr, + size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[], + size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[], + hid_t dxpl_id, void *_buf) { unsigned char *buf=(unsigned char *)_buf; /* Pointer to buffer to fill */ haddr_t abs_eoa; /* Absolute end of file address */ @@ -420,18 +433,10 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, hsize_t max_data; /* Actual maximum size of data to cache */ size_t size; /* Size of sequence in bytes */ size_t u; /* Counting variable */ -#ifndef SLOW_WAY - size_t max_seq; /* Maximum sequence to copy */ - haddr_t temp_end; /* Temporary end of buffer variable */ - size_t max_search; /* Maximum number of sequences to search */ - size_t mask; /* Bit mask */ - int bit_loc; /* Bit location of the leftmost '1' in max_search */ - size_t *size_arr_p; /* Pointer into the size array */ - hsize_t *offset_arr_p; /* Pointer into the offset array */ -#endif /* SLOW_WAY */ - herr_t ret_value=SUCCEED; /* Return value */ + size_t v; /* Counting variable */ + ssize_t ret_value=0; /* Return value */ - FUNC_ENTER_NOAPI(H5F_contig_readv, FAIL); + FUNC_ENTER_NOAPI(H5F_contig_readvv, FAIL); /* Check args */ assert(f); @@ -439,325 +444,143 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, /* Check if data sieving is enabled */ if(f->shared->lf->feature_flags&H5FD_FEAT_DATA_SIEVE) { + 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 */ + + /* Set offsets in sequence lists */ + u=*dset_curr_seq; + v=*mem_curr_seq; + + /* No data sieve buffer yet, go allocate one */ + if(f->shared->sieve_buf==NULL) { + /* Choose smallest buffer to write */ + if(mem_len_arr[v]<dset_len_arr[u]) + size=mem_len_arr[v]; + else + size=dset_len_arr[u]; + + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (unsigned char *)_buf + mem_offset_arr[v]; + + /* Set up the buffer parameters */ + max_data=_max_data-dset_offset_arr[u]; + + /* Check if we can actually hold the I/O request in the sieve buffer */ + if(size>f->shared->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==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - /* Outer loop, guarantees working through all the sequences */ - for(u=0; u<nseq; ) { - - /* Try reading from the data sieve buffer */ - if(f->shared->sieve_buf) { - 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 */ - - /* Stash local copies of these value */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - /* Next-outer loop works through sequences as fast as possible */ - for(; u<nseq; ) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; - - /* 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_end<sieve_end) { - unsigned char *base_sieve_buf=f->shared->sieve_buf+(_addr-sieve_start); - unsigned char *temp_sieve_buf; - haddr_t temp_addr=_addr-1; /* Temporary address */ - -#ifdef SLOW_WAY - /* Retrieve all the sequences out of the current sieve buffer */ - while(contig_end<sieve_end) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+offset_arr[u]; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,size_arr[u]); - - /* Increment offset in buffer */ - buf += size_arr[u]; - - /* Increment sequence number, check for finished with sequences */ - if((++u) >= nseq) - break; - - /* Re-compute end of sequence to retrieve */ - contig_end=temp_addr+offset_arr[u]+size_arr[u]; - } /* end while */ -#else /* SLOW_WAY */ - /* Find log2(n) where n is the number of elements to search */ - - /* Set initial parameters */ - mask=(size_t)0xff<<((sizeof(size_t)-1)*8); /* Get a mask for the leftmost byte */ - max_search=((nseq-1)-u)+1; /* Compute 'n' for the log2 */ - assert(max_search>0); /* Sanity check */ - bit_loc=(sizeof(size_t)*8)-1; /* Initial bit location */ - - /* Search for the first byte with a bit set */ - while((max_search & mask)==0) { - mask>>=8; - bit_loc-=8; - } /* end while */ - - /* Switch to searching for a bit */ - mask=1<<bit_loc; - while((max_search & mask)==0) { - mask>>=1; - bit_loc--; - } /* end while */ - - /* location of the leftmost bit, plus 1, is log2(n) */ - max_seq=bit_loc+1; - - /* Don't walk off the array */ - max_seq=MIN(u+max_seq,nseq-1); - - /* Determine if a linear search is faster than a binary search */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - if(temp_end>=sieve_end) { - /* Linear search is faster */ - - /* Set the initial search values */ - max_seq=u; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Search for the first sequence ending greater than the sieve buffer end */ - while(temp_end<sieve_end) { - if(++max_seq>=nseq) - break; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - } /* end while */ - - /* Adjust back one element */ - max_seq--; - - } /* end if */ - else { - size_t lo,hi; /* Low and high bounds for binary search */ - unsigned found=0; /* Flag to indicate bounds have been found */ - - /* Binary search is faster */ - - /* Find the value 'u' which will be beyond the end of the sieve buffer */ - lo=u; - hi=nseq-1; - max_seq=(lo+hi)/2; - while(!found) { - /* Get the address of the end of sequence for the 'max_seq' position */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Current high bound is too large */ - if(temp_end>=sieve_end) { - if((lo+1)<hi) { - hi=max_seq; - max_seq=(lo+hi)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end if */ - /* Current low bound is too small */ - else { - if((lo+1)<hi) { - lo=max_seq; - max_seq=(lo+hi+1)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end else */ - } /* end while */ - - /* Check for non-exact match */ - if(lo!=hi) { - temp_end=temp_addr+offset_arr[hi]+size_arr[hi]; - if(temp_end<sieve_end) - max_seq=hi; - else - max_seq=lo; - } /* end if */ - } /* end else */ - - /* Set the pointers to the correct locations in the offset & size arrays */ - size_arr_p=&size_arr[u]; - offset_arr_p=&offset_arr[u]; - -#ifdef NO_DUFFS_DEVICE - /* Retrieve all the sequences out of the current sieve buffer */ - while(u<=max_seq) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - } /* end while */ -#else /* NO_DUFFS_DEVICE */ -{ - size_t seq_count; - - seq_count=(max_seq-u)+1; - switch (seq_count % 4) { - case 0: - do - { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - case 3: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - case 2: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - case 1: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - } while (u<=max_seq); - } /* end switch */ - -} -#endif /* NO_DUFFS_DEVICE */ -#endif /* SLOW_WAY */ - } /* 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>f->shared->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(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - } /* end if */ - - /* Read directly into the user's buffer */ - if (H5F_block_read(f, type, 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(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - - /* Determine the new sieve buffer size & location */ - f->shared->sieve_loc=addr; - - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); + /* Determine the new sieve buffer size & location */ + f->shared->sieve_loc=addr; - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-f->shared->base_addr; + /* Make certain we don't read off the end of the file */ + if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - /* Only need this when resizing sieve buffer */ - max_data=_max_data-offset_arr[u]; + /* Adjust absolute EOA address to relative EOA address */ + rel_eoa=abs_eoa-f->shared->base_addr; - /* 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(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); + /* Compute the size of the sieve buffer */ + H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - /* Update local copies of sieve information */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->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,f->shared->sieve_buf,size); - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; + } /* end else */ - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(buf,f->shared->sieve_buf,size); - } /* end else */ + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) + u++; - /* Increment sequence number */ - u++; - } /* end else */ - } /* end for */ + /* Increment number of bytes copied */ + ret_value+=size; + } /* end if */ + + /* Stash local copies of these value */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; + + /* Works through sequences as fast as possible */ + for(; u<dset_max_nseq && v<mem_max_nseq; ) { + /* Choose smallest buffer to write */ + if(mem_len_arr[v]<dset_len_arr[u]) + size=mem_len_arr[v]; + else + size=dset_len_arr[u]; + + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (unsigned char *)_buf + mem_offset_arr[v]; + + /* 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_end<sieve_end) { + unsigned char *base_sieve_buf=f->shared->sieve_buf+(addr-sieve_start); + + /* Grab the data out of the buffer */ + HDmemcpy(buf,base_sieve_buf,size); } /* end if */ - /* No data sieve buffer yet, go allocate one */ + /* Entire request is not within this data sieve buffer */ else { - /* Set up the buffer parameters */ - size=size_arr[u]; - addr=_addr+offset_arr[u]; - max_data=_max_data-offset_arr[u]; - /* Check if we can actually hold the I/O request in the sieve buffer */ if(size>f->shared->sieve_buf_size) { - if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0) + /* 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(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + f->shared->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 { - /* Allocate room for the data sieve buffer */ - if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + /* Flush the sieve buffer if it's dirty */ + if(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; + } /* end if */ /* Determine the new sieve buffer size & location */ f->shared->sieve_loc=addr; @@ -769,59 +592,103 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, /* Adjust absolute EOA address to relative EOA address */ rel_eoa=abs_eoa-f->shared->base_addr; + /* Only need this when resizing sieve buffer */ + max_data=_max_data-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(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); + /* Update local copies of sieve information */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; + /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ HDmemcpy(buf,f->shared->sieve_buf,size); + + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; } /* end else */ + } /* end else */ - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - /* Increment sequence number */ + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) u++; - } /* end else */ + + /* Increment number of bytes copied */ + ret_value+=size; } /* end for */ } /* end if */ else { /* Work through all the sequences */ - for(u=0; u<nseq; u++) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; + for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) { + /* Choose smallest buffer to write */ + if(mem_len_arr[v]<dset_len_arr[u]) + size=mem_len_arr[v]; + else + size=dset_len_arr[u]; - if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (unsigned char *)_buf + mem_offset_arr[v]; + + /* Write data */ + if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - /* Increment offset in buffer */ - buf += size_arr[u]; + /* 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 for */ } /* end else */ + /* Update current sequence vectors */ + *dset_curr_seq=u; + *mem_curr_seq=v; + done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_contig_readv() */ +} /* end H5F_contig_readvv() */ /*------------------------------------------------------------------------- - * Function: H5F_contig_writev + * Function: H5F_contig_writevv * - * Purpose: Writes some data vectors into a dataset from a buffer. - * The data is contiguous. The address is the start of the dataset, + * Purpose: Writes some data vectors into a dataset from vectors into a + * buffer. The address is the start of the dataset, * relative to the base address for the file and the offsets and * sequence lengths are in bytes. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Thursday, July 5, 2001 + * Friday, May 2, 2003 * * Notes: * Offsets in the sequences must be monotonically increasing @@ -830,10 +697,11 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, - size_t nseq, size_t size_arr[], hsize_t offset_arr[], hid_t dxpl_id, - const void *_buf) +ssize_t +H5F_contig_writevv(H5F_t *f, hsize_t _max_data, haddr_t _addr, + size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[], + size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[], + hid_t dxpl_id, const void *_buf) { const unsigned char *buf=_buf; /* Pointer to buffer to fill */ haddr_t abs_eoa; /* Absolute end of file address */ @@ -842,18 +710,10 @@ H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, hsize_t max_data; /* Actual maximum size of data to cache */ size_t size; /* Size of sequence in bytes */ size_t u; /* Counting variable */ -#ifndef SLOW_WAY - size_t max_seq; /* Maximum sequence to copy */ - haddr_t temp_end; /* Temporary end of buffer variable */ - size_t max_search; /* Maximum number of sequences to search */ - size_t mask; /* Bit mask */ - int bit_loc; /* Bit location of the leftmost '1' in max_search */ - size_t *size_arr_p; /* Pointer into the size array */ - hsize_t *offset_arr_p; /* Pointer into the offset array */ -#endif /* SLOW_WAY */ - herr_t ret_value=SUCCEED; /* Return value */ + size_t v; /* Counting variable */ + ssize_t ret_value=0; /* Return value */ - FUNC_ENTER_NOAPI(H5F_contig_writev, FAIL); + FUNC_ENTER_NOAPI(H5F_contig_writevv, FAIL); /* Check args */ assert(f); @@ -861,421 +721,284 @@ H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, /* Check if data sieving is enabled */ if(f->shared->lf->feature_flags&H5FD_FEAT_DATA_SIEVE) { + 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 */ + + /* Set offsets in sequence lists */ + u=*dset_curr_seq; + v=*mem_curr_seq; + + /* No data sieve buffer yet, go allocate one */ + if(f->shared->sieve_buf==NULL) { + /* Choose smallest buffer to write */ + if(mem_len_arr[v]<dset_len_arr[u]) + size=mem_len_arr[v]; + else + size=dset_len_arr[u]; + + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (const unsigned char *)_buf + mem_offset_arr[v]; + + /* Set up the buffer parameters */ + max_data=_max_data-dset_offset_arr[u]; + + /* Check if we can actually hold the I/O request in the sieve buffer */ + if(size>f->shared->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==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - /* Outer loop, guarantees working through all the sequences */ - for(u=0; u<nseq; ) { - - /* Try writing into the data sieve buffer */ - if(f->shared->sieve_buf) { - 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 */ - - /* Stash local copies of these value */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - /* Next-outer loop works through sequences as fast as possible */ - for(; u<nseq; ) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; - - /* Compute end of sequence to retrieve */ - contig_end=addr+size-1; - - /* If entire write is within the sieve buffer, write it to the buffer */ - if(addr>=sieve_start && contig_end<sieve_end) { - unsigned char *base_sieve_buf=f->shared->sieve_buf+(_addr-sieve_start); - unsigned char *temp_sieve_buf; - haddr_t temp_addr=_addr-1; /* Temporary address */ - -#ifdef SLOW_WAY - /* Retrieve all the sequences out of the current sieve buffer */ - while(contig_end<sieve_end) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+offset_arr[u]; - - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,size_arr[u]); - - /* Increment offset in buffer */ - buf += size_arr[u]; - - /* Increment sequence number, check for finished with sequences */ - if((++u) >= nseq) - break; - - /* Re-compute end of sequence to retrieve */ - contig_end=temp_addr+offset_arr[u]+size_arr[u]; - } /* end while */ -#else /* SLOW_WAY */ - /* Find log2(n) where n is the number of elements to search */ - - /* Set initial parameters */ - mask=(size_t)0xff<<((sizeof(size_t)-1)*8); /* Get a mask for the leftmost byte */ - max_search=((nseq-1)-u)+1; /* Compute 'n' for the log2 */ - assert(max_search>0); /* Sanity check */ - bit_loc=(sizeof(size_t)*8)-1; /* Initial bit location */ - - /* Search for the first byte with a bit set */ - while((max_search & mask)==0) { - mask>>=8; - bit_loc-=8; - } /* end while */ - - /* Switch to searching for a bit */ - mask=1<<bit_loc; - while((max_search & mask)==0) { - mask>>=1; - bit_loc--; - } /* end while */ - - /* location of the leftmost bit, plus 1, is log2(n) */ - max_seq=bit_loc+1; - - /* Don't walk off the array */ - max_seq=MIN(u+max_seq,nseq-1); - - /* Determine if a linear search is faster than a binary search */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - if(temp_end>=sieve_end) { - /* Linear search is faster */ - - /* Set the initial search values */ - max_seq=u; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Search for the first sequence ending greater than the sieve buffer end */ - while(temp_end<sieve_end) { - if(++max_seq>=nseq) - break; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - } /* end while */ - - /* Adjust back one element */ - max_seq--; - - } /* end if */ - else { - size_t lo,hi; /* Low and high bounds for binary search */ - unsigned found=0; /* Flag to indicate bounds have been found */ - - /* Binary search is faster */ - - /* Find the value 'u' which will be beyond the end of the sieve buffer */ - lo=u; - hi=nseq-1; - max_seq=(lo+hi)/2; - while(!found) { - /* Get the address of the end of sequence for the 'max_seq' position */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Current high bound is too large */ - if(temp_end>=sieve_end) { - if((lo+1)<hi) { - hi=max_seq; - max_seq=(lo+hi)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end if */ - /* Current low bound is too small */ - else { - if((lo+1)<hi) { - lo=max_seq; - max_seq=(lo+hi+1)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end else */ - } /* end while */ - - /* Check for non-exact match */ - if(lo!=hi) { - temp_end=temp_addr+offset_arr[hi]+size_arr[hi]; - if(temp_end<sieve_end) - max_seq=hi; - else - max_seq=lo; - } /* end if */ - } /* end else */ - - /* Set the pointers to the correct locations in the offset & size arrays */ - size_arr_p=&size_arr[u]; - offset_arr_p=&offset_arr[u]; - -#ifdef NO_DUFFS_DEVICE - /* Retrieve all the sequences out of the current sieve buffer */ - while(u<=max_seq) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Determine the new sieve buffer size & location */ + f->shared->sieve_loc=addr; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Make certain we don't read off the end of the file */ + if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Adjust absolute EOA address to relative EOA address */ + rel_eoa=abs_eoa-f->shared->base_addr; - /* Increment the offset in the array */ - u++; - } /* end while */ -#else /* NO_DUFFS_DEVICE */ -{ - size_t seq_count; + /* Compute the size of the sieve buffer */ + H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - seq_count=(max_seq-u)+1; - switch (seq_count % 4) { - case 0: - do - { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Check if there is any point in reading the data from the file */ + if(f->shared->sieve_size>size) { + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + } /* end if */ - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Grab the data out of the buffer (must be first piece of data in buffer ) */ + HDmemcpy(f->shared->sieve_buf,buf,size); - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Set sieve buffer dirty flag */ + f->shared->sieve_dirty=1; + } /* end else */ - /* Increment the offset in the array */ - u++; + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - case 3: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) + u++; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Increment number of bytes copied */ + ret_value+=size; + } /* end if */ - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Stash local copies of these value */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; + + /* Works through sequences as fast as possible */ + for(; u<dset_max_nseq && v<mem_max_nseq; ) { + /* Choose smallest buffer to write */ + if(mem_len_arr[v]<dset_len_arr[u]) + size=mem_len_arr[v]; + else + size=dset_len_arr[u]; - /* Increment the offset in the array */ - u++; + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; - case 2: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Compute offset in memory */ + buf = (const unsigned char *)_buf + mem_offset_arr[v]; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Compute end of sequence to retrieve */ + contig_end=addr+size-1; - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* If entire write is within the sieve buffer, write it to the buffer */ + if(addr>=sieve_start && contig_end<sieve_end) { + unsigned char *base_sieve_buf=f->shared->sieve_buf+(addr-sieve_start); - /* Increment the offset in the array */ - u++; + /* Put the data into the sieve buffer */ + HDmemcpy(base_sieve_buf,buf,size); - case 1: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Set sieve buffer dirty flag */ + f->shared->sieve_dirty=1; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + } /* 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>f->shared->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(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; + } /* end if */ - /* Increment the offset in the array */ - u++; + /* Force the sieve buffer to be re-read the next time */ + f->shared->sieve_loc=HADDR_UNDEF; + f->shared->sieve_size=0; + } /* end if */ - } while (u<=max_seq); - } /* end switch */ + /* 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 */ + 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)<=f->shared->sieve_buf_size && + f->shared->sieve_dirty) { + /* Prepend to existing sieve buffer */ + if((addr+size)==sieve_start) { + /* Move existing sieve information to correct location */ + HDmemmove(f->shared->sieve_buf+size,f->shared->sieve_buf,sieve_size); + + /* Copy in new information (must be first in sieve buffer) */ + HDmemcpy(f->shared->sieve_buf,buf,size); + + /* Adjust sieve location */ + f->shared->sieve_loc=addr; + + } /* end if */ + /* Append to existing sieve buffer */ + else { + /* Copy in new information */ + HDmemcpy(f->shared->sieve_buf+sieve_size,buf,size); + } /* end else */ -} -#endif /* NO_DUFFS_DEVICE */ -#endif /* SLOW_WAY */ - /* Set sieve buffer dirty flag */ - f->shared->sieve_dirty=1; + /* Adjust sieve size */ + f->shared->sieve_size += size; + + /* Update local copies of sieve information */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; } /* end if */ - /* Entire request is not within this data sieve buffer */ + /* Can't add the new data onto the existing sieve buffer */ else { - /* Check if we can actually hold the I/O request in the sieve buffer */ - if(size>f->shared->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(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - - /* Force the sieve buffer to be re-read the next time */ - f->shared->sieve_loc=HADDR_UNDEF; - f->shared->sieve_size=0; - } /* end if */ - - /* Write directly from the user's buffer */ - if (H5F_block_write(f, type, addr, size, dxpl_id, buf)<0) + /* Flush the sieve buffer if it's dirty */ + if(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; } /* end if */ - /* Element size fits within the buffer size */ - 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)<=f->shared->sieve_buf_size && - f->shared->sieve_dirty) { - /* Prepend to existing sieve buffer */ - if((addr+size)==sieve_start) { - /* Move existing sieve information to correct location */ - HDmemmove(f->shared->sieve_buf+size,f->shared->sieve_buf,sieve_size); - - /* Copy in new information (must be first in sieve buffer) */ - HDmemcpy(f->shared->sieve_buf,buf,size); - - /* Adjust sieve location */ - f->shared->sieve_loc=addr; - - } /* end if */ - /* Append to existing sieve buffer */ - else { - /* Copy in new information */ - HDmemcpy(f->shared->sieve_buf+sieve_size,buf,size); - } /* end else */ - - /* Adjust sieve size */ - f->shared->sieve_size += size; - - /* Update local copies of sieve information */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - } /* end if */ - /* Can't add the new data onto the existing sieve buffer */ - else { - /* Flush the sieve buffer if it's dirty */ - if(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - - /* Determine the new sieve buffer size & location */ - f->shared->sieve_loc=addr; - - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-f->shared->base_addr; - - /* Only need this when resizing sieve buffer */ - max_data=_max_data-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(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - - /* Update local copies of sieve information */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - /* Check if there is any point in reading the data from the file */ - if(f->shared->sieve_size>size) { - /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - } /* end if */ - - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(f->shared->sieve_buf,buf,size); - - /* Set sieve buffer dirty flag */ - f->shared->sieve_dirty=1; - - } /* end else */ - } /* end else */ - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Determine the new sieve buffer size & location */ + f->shared->sieve_loc=addr; - /* Increment sequence number */ - u++; - } /* end else */ - } /* end for */ - } /* end if */ - /* No data sieve buffer yet, go allocate one */ - else { - /* Set up the buffer parameters */ - size=size_arr[u]; - addr=_addr+offset_arr[u]; - max_data=_max_data-offset_arr[u]; + /* Make certain we don't read off the end of the file */ + if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - /* Check if we can actually hold the I/O request in the sieve buffer */ - if(size>f->shared->sieve_buf_size) { - if (H5F_block_write(f, type, 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==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + /* Adjust absolute EOA address to relative EOA address */ + rel_eoa=abs_eoa-f->shared->base_addr; - /* Determine the new sieve buffer size & location */ - f->shared->sieve_loc=addr; + /* Only need this when resizing sieve buffer */ + max_data=_max_data-dset_offset_arr[u]; - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file 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(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-f->shared->base_addr; + /* Update local copies of sieve information */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; - /* Compute the size of the sieve buffer */ - H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); + /* Check if there is any point in reading the data from the file */ + if(f->shared->sieve_size>size) { + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + } /* end if */ - /* Check if there is any point in reading the data from the file */ - if(f->shared->sieve_size>size) { - /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - } /* end if */ + /* Grab the data out of the buffer (must be first piece of data in buffer ) */ + HDmemcpy(f->shared->sieve_buf,buf,size); - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(f->shared->sieve_buf,buf,size); + /* Set sieve buffer dirty flag */ + f->shared->sieve_dirty=1; - /* Set sieve buffer dirty flag */ - f->shared->sieve_dirty=1; + } /* end else */ } /* end else */ + } /* end else */ - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - /* Increment sequence number */ + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) u++; - } /* end else */ + + /* Increment number of bytes copied */ + ret_value+=size; } /* end for */ } /* end if */ else { /* Work through all the sequences */ - for(u=0; u<nseq; u++) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; + for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) { + /* Choose smallest buffer to write */ + if(mem_len_arr[v]<dset_len_arr[u]) + size=mem_len_arr[v]; + else + size=dset_len_arr[u]; - if (H5F_block_write(f, type, addr, size, dxpl_id, buf)<0) + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (const unsigned char *)_buf + mem_offset_arr[v]; + + /* Write data */ + if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - /* Increment offset in buffer */ - buf += size_arr[u]; + /* 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 for */ } /* end else */ + /* Update current sequence vectors */ + *dset_curr_seq=u; + *mem_curr_seq=v; + done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_contig_writev() */ +} /* end H5F_contig_writevv() */ |