/* CVS info */ /* $Date: 2007/03/14 20:16:46 $ */ /* $Revision: 1.5 $ */ /* $RCSfile: read_write_io.c,v $ */ /* $Name: rel_7 $ */ /* This file contains the lowlevel programs that deal with files. ch_p_reads report partial reads ch_p_writes report partial writes syserror convert errno to words bm_read read a file bm_write write a file bm_close close a file bm_open open a file bm_lseek seek to a position in a file */ #include #include #include #include #include #include #include "iobench.h" // The macro GOODBLKSZ is a tunable number. Routines // nbm_read and nbm_write use this number. Large IO // is divided into operations of this size. #ifndef GOODBLKSZ # define GOODBLKSZ (4*1024*1024) #endif extern long jobid; #define SYSERROR(MSG) syserror(__LINE__, __FILE__, __func__, MSG) int partial_read = 0; int partial_writes = 0; int r_err_type = 0; int w_err_type = 0; int o_err_type = 0; int c_err_type = 0; void ch_p_reads( void ){ if( partial_read ) fprintf(stderr,"%d partial reads\n", partial_read ); } void ch_p_writes( void ){ if( partial_writes ) fprintf(stderr,"%d partial writes\n", partial_writes ); } static void syserror(int line, char* file, const char* func, char* msg){ fprintf(stderr,"%04ld %s", jobid, msg); fprintf(stderr,"%s ", strerror( errno ) ); fprintf(stderr,"in function %s in file %s at line %d\n", func, file, line ); } //97 ssize_t bm_read( int fd, const void *buf, size_t nbyte ){ ssize_t nread = 0, n; do { errno = 0; if((n = read(fd, &((char *)buf)[nread], nbyte - nread)) == -1){ if (errno == EINTR){ partial_read++; continue; }else{ r_err_type = errno; SYSERROR( "READ ERROR: " ); return (ssize_t) -1; } } if (n == 0) return nread; nread += n; }while (nread < nbyte); return nread; } // 95 ssize_t bm_write( int fd, const void *buf, size_t nbyte ){ ssize_t nwritten = 0, n; int partial_writes = 0; do { errno = 0; if(( n = write(fd, &((const char *) buf)[nwritten], nbyte - nwritten)) == -1){ if(errno == EINTR){ partial_writes++; continue; } else{ w_err_type = errno; SYSERROR( "WRITE ERROR: " ); return -1; } } nwritten += n; } while ( nwritten < nbyte ); return nwritten; } int bm_close( int fd ){ errno = 0; if ( close( fd ) == -1 ){ c_err_type = errno; SYSERROR( "CLOSE ERROR: " ); return -1; } return 0; } int bm_open( const char *path, int flags, mode_t perms){ int fd; errno = 0; if((fd = open( path, flags, perms)) == -1){ SYSERROR( "OPEN ERROR: " ); } return fd; } off_t bm_lseek( int fd, off_t pos, int whence ){ errno = 0; off_t new_off; if( (new_off = lseek( fd, pos, whence ) ) == (off_t) -1 ){ SYSERROR( "LSEEK ERROR: " ); } return new_off; } ssize_t nbm_read( const int fd, const void *buf, const size_t nbyte ){ ssize_t nread, // Number of bytes read into current block tnread = 0, // Total number of bytes read n, b_per_chunk, // Bytes in a full or partial block bcnt, // Number of blocks to read chnksz = GOODBLKSZ; int i; // Convert a read of nbytes into bcnt reads. The first read is // either a full or partial chunk of data. Any remaining data is // read as full chunks. bcnt = (nbyte + chnksz - 1)/chnksz; // Count of full and partial blocks b_per_chunk = nbyte % chnksz; // Any remaining bytes if ( b_per_chunk == 0 ){ b_per_chunk = chnksz; } for( i=0; i