mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-01-30 15:32:37 +08:00
d84e6e525e
Update Description: Final support addition for FPHDF5. Wherever there was an equivalent MPIO or MPIO/POSIX call/check, I placed an FPHDF5 call/check there as well, with the appropriate #ifdefs in place. The hdf5.h is updated with the H5FDfphdf5.h driver #include. Platforms tested: Linux & Modi4
1235 lines
55 KiB
C
1235 lines
55 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
* Copyright by the Board of Trustees of the University of Illinois. *
|
||
* All rights reserved. *
|
||
* *
|
||
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
||
* terms governing use, modification, and redistribution, is contained in *
|
||
* the files COPYING and Copyright.html. COPYING can be found at the root *
|
||
* of the source code distribution tree; Copyright.html can be found at the *
|
||
* root level of an installed copy of the electronic HDF5 document set and *
|
||
* is linked from the top-level documents page. It can also be found at *
|
||
* http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
|
||
* access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
||
/*
|
||
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
|
||
* Thursday, September 28, 2000
|
||
*
|
||
* 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.
|
||
*/
|
||
|
||
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
|
||
|
||
#include "H5private.h" /* Generic Functions */
|
||
#include "H5Dprivate.h" /* Dataset functions */
|
||
#include "H5Eprivate.h" /* Error handling */
|
||
#include "H5Fpkg.h"
|
||
#include "H5FDprivate.h" /*file driver */
|
||
#include "H5FLprivate.h" /*Free Lists */
|
||
#include "H5Oprivate.h" /* Object headers */
|
||
#include "H5Pprivate.h" /* Property lists */
|
||
#include "H5Vprivate.h" /* Vector and array functions */
|
||
|
||
/* MPIO, MPIPOSIX, & FPHDF5 drivers needed for special checks */
|
||
#include "H5FDfphdf5.h"
|
||
#include "H5FDmpio.h"
|
||
#include "H5FDmpiposix.h"
|
||
|
||
/* Interface initialization */
|
||
#define PABLO_MASK H5Fcontig_mask
|
||
static int interface_initialize_g = 0;
|
||
#define INTERFACE_INIT NULL
|
||
|
||
/* Declare a PQ free list to manage the sieve buffer information */
|
||
H5FL_BLK_DEFINE(sieve_buf);
|
||
|
||
/* Declare the free list to manage blocks of non-zero fill-value data */
|
||
H5FL_BLK_DEFINE_STATIC(non_zero_fill);
|
||
|
||
/* Declare the free list to manage blocks of zero fill-value data */
|
||
H5FL_BLK_DEFINE_STATIC(zero_fill);
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_contig_fill
|
||
*
|
||
* Purpose: Write fill values to a contiguously stored dataset.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* August 22, 2002
|
||
*
|
||
* Modifications:
|
||
* Bill Wendling, February 20, 2003
|
||
* Added support for getting the barrier COMM if you're using
|
||
* Flexible PHDF5.
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
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,
|
||
const struct H5O_fill_t *fill, size_t elmt_size)
|
||
{
|
||
hssize_t snpoints; /* Number of points in space (for error checking) */
|
||
size_t npoints; /* Number of points in space */
|
||
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 */
|
||
void *buf = NULL; /* Buffer for fill value writing */
|
||
#ifdef H5_HAVE_PARALLEL
|
||
MPI_Comm mpi_comm=MPI_COMM_NULL; /* MPI communicator for file */
|
||
int mpi_rank=(-1); /* This process's rank */
|
||
int mpi_size=(-1); /* Total # of processes */
|
||
int mpi_round=0; /* Current process responsible for I/O */
|
||
int mpi_code; /* MPI return code */
|
||
unsigned blocks_written=0; /* Flag to indicate that chunk was actually written */
|
||
unsigned using_mpi=0; /* Flag to indicate that the file is being accessed with an MPI-capable file driver */
|
||
#endif /* H5_HAVE_PARALLEL */
|
||
int non_zero_fill_f=(-1); /* Indicate that a non-zero fill-value was used */
|
||
herr_t ret_value=SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI(H5F_contig_fill, FAIL);
|
||
|
||
/* Check args */
|
||
assert(f);
|
||
assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER));
|
||
assert(layout && H5D_CONTIGUOUS==layout->type);
|
||
assert(layout->ndims>0 && layout->ndims<=H5O_LAYOUT_NDIMS);
|
||
assert(H5F_addr_defined(layout->addr));
|
||
assert(dc_plist!=NULL);
|
||
assert(space);
|
||
assert(elmt_size>0);
|
||
|
||
#ifdef H5_HAVE_PARALLEL
|
||
/* Retrieve up MPI parameters */
|
||
if(IS_H5FD_MPIO(f)) {
|
||
/* Get the MPI communicator */
|
||
if (MPI_COMM_NULL == (mpi_comm=H5FD_mpio_communicator(f->shared->lf)))
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI communicator");
|
||
|
||
/* Get the MPI rank & size */
|
||
if ((mpi_rank=H5FD_mpio_mpi_rank(f->shared->lf))<0)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI rank");
|
||
if ((mpi_size=H5FD_mpio_mpi_size(f->shared->lf))<0)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI size");
|
||
|
||
/* Set the MPI-capable file driver flag */
|
||
using_mpi=1;
|
||
} /* end if */
|
||
else if(IS_H5FD_MPIPOSIX(f)) {
|
||
/* Get the MPI communicator */
|
||
if (MPI_COMM_NULL == (mpi_comm=H5FD_mpiposix_communicator(f->shared->lf)))
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI communicator");
|
||
|
||
/* Get the MPI rank & size */
|
||
if ((mpi_rank=H5FD_mpiposix_mpi_rank(f->shared->lf))<0)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI rank");
|
||
if ((mpi_size=H5FD_mpiposix_mpi_size(f->shared->lf))<0)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI size");
|
||
|
||
/* Set the MPI-capable file driver flag */
|
||
using_mpi=1;
|
||
} /* end if */
|
||
#ifdef H5_HAVE_FPHDF5
|
||
else if (IS_H5FD_FPHDF5(f)) {
|
||
/* Get the FPHDF5 barrier communicator */
|
||
if (MPI_COMM_NULL == (mpi_comm = H5FD_fphdf5_barrier_communicator(f->shared->lf)))
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI communicator");
|
||
|
||
/* Get the MPI rank & size */
|
||
if ((mpi_rank = H5FD_fphdf5_mpi_rank(f->shared->lf)) < 0)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI rank");
|
||
|
||
if ((mpi_size = H5FD_fphdf5_mpi_size(f->shared->lf)) < 0)
|
||
HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI size");
|
||
|
||
/* Set the MPI-capable file driver flag */
|
||
using_mpi = 1;
|
||
} /* end if */
|
||
#endif /* H5_HAVE_FPHDF5 */
|
||
#endif /* H5_HAVE_PARALLEL */
|
||
|
||
/* Get the number of elements in the dataset's dataspace */
|
||
snpoints = H5S_get_simple_extent_npoints(space);
|
||
assert(snpoints>=0);
|
||
H5_ASSIGN_OVERFLOW(npoints,snpoints,hssize_t,size_t);
|
||
|
||
/* If fill value is not library default, use it to set the element size */
|
||
if(fill->buf)
|
||
elmt_size=fill->size;
|
||
|
||
/*
|
||
* Fill the entire current extent with the fill value. We can do
|
||
* 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;
|
||
|
||
/* Fill the buffer with the user's fill value */
|
||
if(fill->buf) {
|
||
/* Allocate temporary buffer */
|
||
if ((buf=H5FL_BLK_MALLOC(non_zero_fill,bufsize))==NULL)
|
||
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer");
|
||
|
||
H5V_array_fill(buf, fill->buf, elmt_size, ptsperbuf);
|
||
|
||
/* Indicate that a non-zero fill buffer was used */
|
||
non_zero_fill_f=1;
|
||
} /* end if */
|
||
else { /* Fill the buffer with the default fill value */
|
||
htri_t buf_avail;
|
||
|
||
/* Check if there is an already zeroed out buffer available */
|
||
buf_avail=H5FL_BLK_AVAIL(zero_fill,bufsize);
|
||
assert(buf_avail!=FAIL);
|
||
|
||
/* Allocate temporary buffer (zeroing it if no buffer is available) */
|
||
if(!buf_avail)
|
||
buf=H5FL_BLK_CALLOC(zero_fill,bufsize);
|
||
else
|
||
buf=H5FL_BLK_MALLOC(zero_fill,bufsize);
|
||
if(buf==NULL)
|
||
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer");
|
||
|
||
/* Indicate that a zero fill buffer was used */
|
||
non_zero_fill_f=0;
|
||
} /* end else */
|
||
|
||
/* Start at the beginning of the dataset */
|
||
addr = 0;
|
||
|
||
/* Loop through writing the fill value to the dataset */
|
||
while (npoints>0) {
|
||
size = MIN(ptsperbuf, npoints) * elmt_size;
|
||
|
||
#ifdef H5_HAVE_PARALLEL
|
||
/* Check if this file is accessed with an MPI-capable file driver */
|
||
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)
|
||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset");
|
||
} /* end if */
|
||
mpi_round=(++mpi_round)%mpi_size;
|
||
|
||
/* Indicate that blocks are being written */
|
||
blocks_written=1;
|
||
} /* 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)
|
||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset");
|
||
#ifdef H5_HAVE_PARALLEL
|
||
} /* end else */
|
||
#endif /* H5_HAVE_PARALLEL */
|
||
|
||
npoints -= MIN(ptsperbuf, npoints);
|
||
addr += size;
|
||
} /* end while */
|
||
|
||
#ifdef H5_HAVE_PARALLEL
|
||
/* Only need to block at the barrier if we actually wrote fill values */
|
||
/* And if we are using an MPI-capable file driver */
|
||
if(using_mpi && blocks_written) {
|
||
/* Wait at barrier to avoid race conditions where some processes are
|
||
* still writing out fill values and other processes race ahead to data
|
||
* in, getting bogus data.
|
||
*/
|
||
if (MPI_SUCCESS != (mpi_code=MPI_Barrier(mpi_comm)))
|
||
HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code);
|
||
} /* end if */
|
||
#endif /* H5_HAVE_PARALLEL */
|
||
|
||
done:
|
||
/* Free the buffer for fill values */
|
||
if (buf) {
|
||
assert(non_zero_fill_f>=0);
|
||
if(non_zero_fill_f)
|
||
H5FL_BLK_FREE(non_zero_fill,buf);
|
||
else
|
||
H5FL_BLK_FREE(zero_fill,buf);
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* 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.
|
||
* 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_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)
|
||
{
|
||
hsize_t offset=0; /* Offset for vector call */
|
||
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)
|
||
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed");
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
} /* end H5F_contig_write() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_contig_readv
|
||
*
|
||
* Purpose: Reads some data vectors from a dataset into a buffer.
|
||
* The data is contiguous. 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
|
||
* Friday, May 3, 2001
|
||
*
|
||
* Notes:
|
||
* Offsets in the sequences must be monotonically increasing
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
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*/)
|
||
{
|
||
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 */
|
||
#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 */
|
||
|
||
FUNC_ENTER_NOAPI(H5F_contig_readv, FAIL);
|
||
|
||
/* Check args */
|
||
assert(f);
|
||
assert(buf);
|
||
|
||
/* Check if data sieving is enabled */
|
||
if(f->shared->lf->feature_flags&H5FD_FEAT_DATA_SIEVE) {
|
||
|
||
/* 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");
|
||
|
||
/* 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;
|
||
|
||
/* 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");
|
||
|
||
/* 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);
|
||
} /* end else */
|
||
|
||
/* Increment offset in buffer */
|
||
buf += size_arr[u];
|
||
|
||
/* 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];
|
||
|
||
/* 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)
|
||
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");
|
||
|
||
/* 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;
|
||
|
||
/* 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);
|
||
|
||
/* 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");
|
||
|
||
/* 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);
|
||
} /* end else */
|
||
|
||
/* Increment offset in buffer */
|
||
buf += size_arr[u];
|
||
|
||
/* Increment sequence number */
|
||
u++;
|
||
} /* end else */
|
||
} /* 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];
|
||
|
||
if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0)
|
||
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed");
|
||
|
||
/* Increment offset in buffer */
|
||
buf += size_arr[u];
|
||
} /* end for */
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
} /* end H5F_contig_readv() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5F_contig_writev
|
||
*
|
||
* Purpose: Writes some data vectors into a dataset from a buffer.
|
||
* The data is contiguous. 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
|
||
*
|
||
* Notes:
|
||
* Offsets in the sequences must be monotonically increasing
|
||
*
|
||
* Modifications:
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
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)
|
||
{
|
||
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 */
|
||
#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 */
|
||
|
||
FUNC_ENTER_NOAPI(H5F_contig_writev, FAIL);
|
||
|
||
/* Check args */
|
||
assert(f);
|
||
assert(buf);
|
||
|
||
/* Check if data sieving is enabled */
|
||
if(f->shared->lf->feature_flags&H5FD_FEAT_DATA_SIEVE) {
|
||
|
||
/* 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++;
|
||
|
||
/* Grab the data out of the buffer */
|
||
HDmemcpy(temp_sieve_buf,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(temp_sieve_buf,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(temp_sieve_buf,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(temp_sieve_buf,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(temp_sieve_buf,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 */
|
||
/* Set sieve buffer dirty flag */
|
||
f->shared->sieve_dirty=1;
|
||
|
||
} /* 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 */
|
||
|
||
/* 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)
|
||
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 */
|
||
|
||
/* 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];
|
||
|
||
/* 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];
|
||
|
||
/* 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");
|
||
|
||
/* 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;
|
||
|
||
/* 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, 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 */
|
||
|
||
/* Increment offset in buffer */
|
||
buf += size_arr[u];
|
||
|
||
/* Increment sequence number */
|
||
u++;
|
||
} /* end else */
|
||
} /* 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];
|
||
|
||
if (H5F_block_write(f, type, addr, size, dxpl_id, buf)<0)
|
||
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
|
||
|
||
/* Increment offset in buffer */
|
||
buf += size_arr[u];
|
||
} /* end for */
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value);
|
||
} /* end H5F_contig_writev() */
|
||
|