00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 #include "w_defines.h"
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 #if defined(linux) && !defined(_GNU_SOURCE)
00070 
00071 
00072 
00073 
00074 
00075 #define _GNU_SOURCE
00076 #endif
00077 
00078 #include <w.h>
00079 #include <sthread.h>
00080 #include <sdisk.h>
00081 #include <sdisk_unix.h>
00082 
00083 #ifdef EXPENSIVE_STATS
00084 #include <stime.h>
00085 #endif
00086 
00087 #include <sthread_stats.h>
00088 extern class sthread_stats SthreadStats;
00089 
00090 #include "os_fcntl.h"
00091 #include <cerrno>
00092 #include <sys/stat.h>
00093 
00094 #include <sys/uio.h>
00095 
00096 #define    HAVE_IO_VECTOR
00097 
00098 
00099 
00100 
00101 #include <os_interface.h>
00102 
00103 
00104 const int stBADFD = sthread_base_t::stBADFD;
00105 const int stINVAL = sthread_base_t::stINVAL;
00106 
00107 
00108 int    sdisk_unix_t::convert_flags(int sflags)
00109 {
00110     int    flags = 0;
00111 
00112     
00113     switch (modeBits(sflags)) {
00114     case OPEN_RDWR:
00115         flags |= O_RDWR;
00116         break;
00117     case OPEN_WRONLY:
00118         flags |= O_WRONLY;
00119         break;
00120     case OPEN_RDONLY:
00121         flags |= O_RDONLY;
00122         break;
00123     }
00124 
00125     
00126     
00127     if (hasOption(sflags, OPEN_CREATE))
00128         flags |= O_CREAT;
00129     if (hasOption(sflags, OPEN_TRUNC))
00130         flags |= O_TRUNC;
00131     if (hasOption(sflags, OPEN_EXCL))
00132         flags |= O_EXCL;
00133 #ifdef O_SYNC
00134     if (hasOption(sflags, OPEN_SYNC))
00135         flags |= O_SYNC;
00136 #endif
00137     if (hasOption(sflags, OPEN_APPEND))
00138         flags |= O_APPEND;
00139 #ifdef O_DIRECT
00140     
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154     if (hasOption(sflags, OPEN_RAW))
00155         flags |= O_DIRECT;
00156 #endif
00157 
00158     return flags;
00159 }
00160 
00161 
00162 sdisk_unix_t::~sdisk_unix_t()
00163 {
00164     if (_fd != FD_NONE)
00165         W_COERCE(close());
00166 }
00167 
00168 
00169 w_rc_t    sdisk_unix_t::make(const char *name, int flags, int mode,
00170                sdisk_t *&disk)
00171 {
00172     sdisk_unix_t    *ud;
00173     w_rc_t        e;
00174 
00175     disk = 0;    
00176     
00177     ud = new sdisk_unix_t(name);
00178     if (!ud)
00179         return RC(fcOUTOFMEMORY);
00180 
00181     e = ud->open(name, flags, mode);
00182     if (e.is_error()) {
00183         delete ud;
00184         return e;
00185     }
00186 
00187     disk = ud;
00188     return RCOK;
00189 }
00190 
00191 
00192 w_rc_t    sdisk_unix_t::open(const char *name, int flags, int mode)
00193 {
00194     if (_fd != FD_NONE)
00195         return RC(stBADFD);    
00196 
00197     _fd = ::os_open(name, convert_flags(flags), mode);
00198     if (_fd == -1) {
00199         w_rc_t rc = RC(fcOS);
00200         RC_APPEND_MSG(rc, << "Offending file: " << name);
00201         return rc;
00202     }
00203 
00204     return RCOK;
00205 }
00206 
00207 w_rc_t    sdisk_unix_t::close()
00208 {
00209     if (_fd == FD_NONE)
00210         return RC(stBADFD);    
00211 
00212     int    n;
00213 
00214     n = ::os_close(_fd);
00215     if (n == -1)
00216         return RC(fcOS);
00217 
00218     _fd = FD_NONE;
00219     return RCOK;
00220 }
00221 
00222 
00223 
00224 
00225 w_rc_t    sdisk_unix_t::read(void *buf, int count, int &done)
00226 {
00227     if (_fd == FD_NONE)
00228         return RC(stBADFD);
00229 
00230     int    n;
00231 
00232     INC_STH_STATS(num_io);
00233 
00234     n = ::os_read(_fd, buf, count);
00235     if (n == -1)
00236         return RC(fcOS);
00237 
00238     done = n;
00239 
00240     return RCOK;
00241 }
00242 
00243 w_rc_t    sdisk_unix_t::write(const void *buf, int count, int &done)
00244 {
00245     if (_fd == FD_NONE)
00246         return RC(stBADFD);
00247 
00248     int    n;
00249 
00250     INC_STH_STATS(num_io);
00251 
00252     n = ::os_write(_fd, buf, count);
00253     if (n == -1)
00254         return RC(fcOS);
00255 
00256 #if defined(USING_VALGRIND)
00257     if(RUNNING_ON_VALGRIND)
00258     {
00259         check_valgrind_errors(__LINE__, __FILE__);
00260     }
00261 #endif
00262 
00263     done = n;
00264 
00265     return RCOK;
00266 }
00267 
00268 #ifdef HAVE_IO_VECTOR
00269 w_rc_t    sdisk_unix_t::readv(const iovec_t *iov, int iovcnt, int &done)
00270 {
00271     if (_fd == FD_NONE)
00272         return RC(stBADFD);
00273 
00274     int    n;
00275 
00276     INC_STH_STATS(num_io);
00277 
00278 #ifdef IOVEC_MISMATCH
00279     {
00280         struct iovec _iov[sthread_t::iovec_max];
00281         for (int i = 0; i < iovcnt; i++) {
00282             _iov[i].iov_base = (char *) iov[i].iov_base;
00283             _iov[i].iov_len = iov[i].iov_len;
00284         }
00285         n = ::os_readv(_fd, _iov, iovcnt);
00286     }
00287 #else
00288     n = ::os_readv(_fd, (const struct iovec *)iov, iovcnt);
00289 #endif
00290     if (n == -1)
00291         return RC(fcOS);
00292 
00293     done = n;
00294 
00295     return RCOK;
00296 }
00297 
00298 w_rc_t    sdisk_unix_t::writev(const iovec_t *iov, int iovcnt, int &done)
00299 {
00300     if (_fd == FD_NONE)
00301         return RC(stBADFD);
00302 
00303     int    n;
00304 
00305     INC_STH_STATS(num_io);
00306 
00307 #ifdef IOVEC_MISMATCH
00308     {
00309         struct iovec _iov[sthread_t::iovec_max];
00310         for (int i = 0; i < iovcnt; i++) {
00311             _iov[i].iov_base = (char *) iov[i].iov_base;
00312             _iov[i].iov_len = iov[i].iov_len;
00313         }
00314         n = ::os_writev(_fd, _iov, iovcnt);
00315     }
00316 #else
00317     n = ::os_writev(_fd, (const struct iovec *)iov, iovcnt);
00318 #endif
00319     if (n == -1)
00320         return RC(fcOS);
00321 
00322 #if defined(USING_VALGRIND)
00323     if(RUNNING_ON_VALGRIND)
00324     {
00325         check_valgrind_errors(__LINE__, __FILE__);
00326     }
00327 #endif
00328 
00329     done = n;
00330 
00331     return RCOK;
00332 }
00333 #endif
00334 
00335 w_rc_t    sdisk_unix_t::pread(void *buf, int count, fileoff_t pos, int &done)
00336 {
00337     if (_fd == FD_NONE)
00338         return RC(stBADFD);
00339 
00340     int    n;
00341 
00342     INC_STH_STATS(num_io);
00343 
00344     n = ::os_pread(_fd, buf, count, pos);
00345     if (n == -1)
00346         return RC(fcOS);
00347 
00348     done = n;
00349 
00350     return RCOK;
00351 }
00352 
00353 
00354 w_rc_t    sdisk_unix_t::pwrite(const void *buf, int count, fileoff_t pos,
00355                 int &done)
00356 {
00357     if (_fd == FD_NONE)
00358         return RC(stBADFD);
00359 
00360     int    n;
00361 
00362     INC_STH_STATS(num_io);
00363 
00364     n = ::os_pwrite(_fd, buf, count, pos);
00365     if (n == -1)
00366         return RC(fcOS);
00367 #if defined(USING_VALGRIND)
00368     if(RUNNING_ON_VALGRIND)
00369     {
00370         check_valgrind_errors(__LINE__, __FILE__);
00371     }
00372 #endif
00373 
00374     done = n;
00375 
00376     return RCOK;
00377 }
00378 
00379 w_rc_t    sdisk_unix_t::seek(fileoff_t pos, int origin, fileoff_t &newpos)
00380 {
00381     if (_fd == FD_NONE)
00382         return RC(stBADFD);
00383 
00384     switch (origin) {
00385     case SEEK_AT_SET:
00386         origin = SEEK_SET;
00387         break;
00388     case SEEK_AT_CUR:
00389         origin = SEEK_CUR;
00390         break;
00391     case SEEK_AT_END:
00392         origin = SEEK_END;
00393         break;
00394     }
00395 
00396     fileoff_t    l=0;
00397     l = ::os_lseek(_fd, pos, origin);
00398     if (l == -1)
00399         return RC(fcOS);
00400 
00401     newpos = l;
00402 
00403     return RCOK;
00404 }
00405 
00406 w_rc_t    sdisk_unix_t::truncate(fileoff_t size)
00407 {
00408     if (_fd == FD_NONE)
00409         return RC(stBADFD);
00410     INC_STH_STATS(num_io);
00411     int    n = ::os_ftruncate(_fd, size);
00412     return (n == -1) ? RC(fcOS) : RCOK;
00413 }
00414 
00415 w_rc_t    sdisk_unix_t::sync()
00416 {
00417     if (_fd == FD_NONE)
00418         return RC(stBADFD);
00419 
00420     INC_STH_STATS(num_io);
00421     int n = os_fsync(_fd);
00422 
00423     
00424     if (n == -1 && (errno == EBADF || errno == EINVAL))
00425         n = 0;
00426 
00427     return (n == -1) ? RC(fcOS) : RCOK;
00428 }
00429 
00430 
00431 w_rc_t    sdisk_unix_t::stat(filestat_t &st)
00432 {
00433     if (_fd == FD_NONE)
00434         return RC(stBADFD);
00435 
00436     os_stat_t    sys;
00437     int n = os_fstat(_fd, &sys);
00438     if (n == -1)
00439         return RC(fcOS);
00440 
00441     st.st_size = sys.st_size;
00442 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
00443     st.st_block_size = sys.st_blksize;
00444 #else
00445     st.st_block_size = 512;    
00446 #endif
00447 
00448     st.st_device_id = sys.st_dev;
00449     st.st_file_id = sys.st_ino;
00450 
00451     int mode = (sys.st_mode & S_IFMT);
00452     st.is_file = (mode == S_IFREG);
00453     st.is_dir = (mode == S_IFDIR);
00454 #ifdef S_IFBLK
00455     st.is_device = (mode == S_IFBLK);
00456 #else
00457     st.is_device = false;
00458 #endif
00459     st.is_device = st.is_device || (mode == S_IFCHR);
00460 
00461     return RCOK;
00462 }
00463 
00464