sdisk_unix.cpp

00001 /* -*- mode:C++; c-basic-offset:4 -*-
00002      Shore-MT -- Multi-threaded port of the SHORE storage manager
00003    
00004                        Copyright (c) 2007-2009
00005       Data Intensive Applications and Systems Labaratory (DIAS)
00006                Ecole Polytechnique Federale de Lausanne
00007    
00008                          All Rights Reserved.
00009    
00010    Permission to use, copy, modify and distribute this software and
00011    its documentation is hereby granted, provided that both the
00012    copyright notice and this permission notice appear in all copies of
00013    the software, derivative works or modified versions, and any
00014    portions thereof, and that both notices appear in supporting
00015    documentation.
00016    
00017    This code is distributed in the hope that it will be useful, but
00018    WITHOUT ANY WARRANTY; without even the implied warranty of
00019    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS
00020    DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
00021    RESULTING FROM THE USE OF THIS SOFTWARE.
00022 */
00023 
00024 /*<std-header orig-src='shore'>
00025 
00026  $Id: sdisk_unix.cpp,v 1.25 2010/07/29 21:22:57 nhall Exp $
00027 
00028 SHORE -- Scalable Heterogeneous Object REpository
00029 
00030 Copyright (c) 1994-99 Computer Sciences Department, University of
00031                       Wisconsin -- Madison
00032 All Rights Reserved.
00033 
00034 Permission to use, copy, modify and distribute this software and its
00035 documentation is hereby granted, provided that both the copyright
00036 notice and this permission notice appear in all copies of the
00037 software, derivative works or modified versions, and any portions
00038 thereof, and that both notices appear in supporting documentation.
00039 
00040 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
00041 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
00042 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
00043 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
00044 
00045 This software was developed with support by the Advanced Research
00046 Project Agency, ARPA order number 018 (formerly 8230), monitored by
00047 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
00048 Further funding for this work was provided by DARPA through
00049 Rome Research Laboratory Contract No. F30602-97-2-0247.
00050 
00051 */
00052 
00053 #include "w_defines.h"
00054 
00055 /*  -- do not edit anything above this line --   </std-header>*/
00056 
00057 /**\cond skip */
00058 /*
00059  *   NewThreads I/O is Copyright 1995, 1996, 1997, 1998 by:
00060  *
00061  *    Josef Burger    <bolo@cs.wisc.edu>
00062  *
00063  *   All Rights Reserved.
00064  *
00065  *   NewThreads I/O may be freely used as long as credit is given
00066  *   to the above author(s) and the above copyright is maintained.
00067  */
00068 
00069 #if defined(linux) && !defined(_GNU_SOURCE)
00070 /*
00071  *  XXX this done to make O_DIRECT available as an I/O choice.
00072  *  Unfortunately, it needs to pollute the other headers, otw
00073  *  the features will be set and access won't be possible
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 #include <sthread_stats.h>
00083 extern class sthread_stats SthreadStats;
00084 
00085 #include "os_fcntl.h"
00086 #include <cerrno>
00087 #include <sys/stat.h>
00088 
00089 #include <sys/uio.h>
00090 
00091 #define    HAVE_IO_VECTOR
00092 
00093 // TODO deal with these HAVE_IO* 
00094 // TODO : is vector i/o ok with pthreads?
00095 
00096 #include <os_interface.h>
00097 
00098 
00099 const int stBADFD = sthread_base_t::stBADFD;
00100 // not used DEAD const int stINVAL = sthread_base_t::stINVAL;
00101 
00102 
00103 int    sdisk_unix_t::convert_flags(int sflags)
00104 {
00105     int    flags = 0;
00106 
00107     /* 1 of n */
00108     switch (modeBits(sflags)) {
00109     case OPEN_RDWR:
00110         flags |= O_RDWR;
00111         break;
00112     case OPEN_WRONLY:
00113         flags |= O_WRONLY;
00114         break;
00115     case OPEN_RDONLY:
00116         flags |= O_RDONLY;
00117         break;
00118     }
00119 
00120     /* m of n */
00121     /* could make a data driven flag conversion, :-) */
00122     if (hasOption(sflags, OPEN_CREATE))
00123         flags |= O_CREAT;
00124     if (hasOption(sflags, OPEN_TRUNC))
00125         flags |= O_TRUNC;
00126     if (hasOption(sflags, OPEN_EXCL))
00127         flags |= O_EXCL;
00128 #ifdef O_SYNC
00129     if (hasOption(sflags, OPEN_SYNC))
00130         flags |= O_SYNC;
00131 #endif
00132     if (hasOption(sflags, OPEN_APPEND))
00133         flags |= O_APPEND;
00134 #ifdef O_DIRECT
00135     /*
00136      * From the open man page:
00137      *      O_DIRECT
00138               Try to minimize cache effects of the I/O to and from this  file.
00139               In  general  this  will degrade performance, but it is useful in
00140               special situations, such  as  when  applications  do  their  own
00141               caching.   File I/O is done directly to/from user space buffers.
00142               The I/O is synchronous, i.e., at the completion of a read(2)  or
00143               write(2),  data  is  guaranteed to have been transferred.  Under
00144               Linux 2.4 transfer sizes, and the alignment of user  buffer  and
00145               file  offset  must all be multiples of the logical block size of
00146               the file system. Under Linux 2.6 alignment must  fit  the  block
00147               size of the device.
00148     */
00149     if (hasOption(sflags, OPEN_RAW))
00150         flags |= O_DIRECT;
00151 #endif
00152 
00153     return flags;
00154 }
00155 
00156 
00157 sdisk_unix_t::~sdisk_unix_t()
00158 {
00159     if (_fd != FD_NONE)
00160         W_COERCE(close());
00161 }
00162 
00163 
00164 w_rc_t    sdisk_unix_t::make(const char *name, int flags, int mode,
00165                sdisk_t *&disk)
00166 {
00167     sdisk_unix_t    *ud;
00168     w_rc_t        e;
00169 
00170     disk = 0;    /* default value*/
00171     
00172     ud = new sdisk_unix_t(name);
00173     if (!ud)
00174         return RC(fcOUTOFMEMORY);
00175 
00176     e = ud->open(name, flags, mode);
00177     if (e.is_error()) {
00178         delete ud;
00179         return e;
00180     }
00181 
00182     disk = ud;
00183     return RCOK;
00184 }
00185 
00186 
00187 w_rc_t    sdisk_unix_t::open(const char *name, int flags, int mode)
00188 {
00189     if (_fd != FD_NONE)
00190         return RC(stBADFD);    /* XXX in use */
00191 
00192     _fd = ::os_open(name, convert_flags(flags), mode);
00193     if (_fd == -1) {
00194         w_rc_t rc = RC(fcOS);
00195         RC_APPEND_MSG(rc, << "Offending file: " << name);
00196         return rc;
00197     }
00198 
00199     return RCOK;
00200 }
00201 
00202 w_rc_t    sdisk_unix_t::close()
00203 {
00204     if (_fd == FD_NONE)
00205         return RC(stBADFD);    /* XXX closed */
00206 
00207     int    n;
00208 
00209     n = ::os_close(_fd);
00210     if (n == -1)
00211         return RC(fcOS);
00212 
00213     _fd = FD_NONE;
00214     return RCOK;
00215 }
00216 
00217 
00218 
00219 
00220 w_rc_t    sdisk_unix_t::read(void *buf, int count, int &done)
00221 {
00222     if (_fd == FD_NONE)
00223         return RC(stBADFD);
00224 
00225     int    n;
00226     n = ::os_read(_fd, buf, count);
00227     if (n == -1)
00228         return RC(fcOS);
00229 
00230     done = n;
00231 
00232     return RCOK;
00233 }
00234 
00235 w_rc_t    sdisk_unix_t::write(const void *buf, int count, int &done)
00236 {
00237     if (_fd == FD_NONE)
00238         return RC(stBADFD);
00239 
00240     int    n;
00241 
00242     n = ::os_write(_fd, buf, count);
00243     if (n == -1)
00244         return RC(fcOS);
00245 
00246 #if defined(USING_VALGRIND)
00247     if(RUNNING_ON_VALGRIND)
00248     {
00249         check_valgrind_errors(__LINE__, __FILE__);
00250     }
00251 #endif
00252 
00253     done = n;
00254 
00255     return RCOK;
00256 }
00257 
00258 #ifdef HAVE_IO_VECTOR
00259 w_rc_t    sdisk_unix_t::readv(const iovec_t *iov, int iovcnt, int &done)
00260 {
00261     if (_fd == FD_NONE)
00262         return RC(stBADFD);
00263 
00264     int    n;
00265 
00266     n = ::os_readv(_fd, (const struct iovec *)iov, iovcnt);
00267     if (n == -1)
00268         return RC(fcOS);
00269 
00270     done = n;
00271 
00272     return RCOK;
00273 }
00274 
00275 w_rc_t    sdisk_unix_t::writev(const iovec_t *iov, int iovcnt, int &done)
00276 {
00277     if (_fd == FD_NONE)
00278         return RC(stBADFD);
00279 
00280     int    n;
00281 
00282 #ifdef IOVEC_MISMATCH
00283     {
00284         struct iovec _iov[sthread_t::iovec_max];
00285         for (int i = 0; i < iovcnt; i++) {
00286             _iov[i].iov_base = (char *) iov[i].iov_base;
00287             _iov[i].iov_len = iov[i].iov_len;
00288         }
00289         n = ::os_writev(_fd, _iov, iovcnt);
00290     }
00291 #else
00292     n = ::os_writev(_fd, (const struct iovec *)iov, iovcnt);
00293 #endif
00294     if (n == -1)
00295         return RC(fcOS);
00296 
00297 #if defined(USING_VALGRIND)
00298     if(RUNNING_ON_VALGRIND)
00299     {
00300         check_valgrind_errors(__LINE__, __FILE__);
00301     }
00302 #endif
00303 
00304     done = n;
00305 
00306     return RCOK;
00307 }
00308 #endif
00309 
00310 w_rc_t    sdisk_unix_t::pread(void *buf, int count, fileoff_t pos, int &done)
00311 {
00312     if (_fd == FD_NONE)
00313         return RC(stBADFD);
00314 
00315     int    n;
00316 
00317     n = ::os_pread(_fd, buf, count, pos);
00318     if (n == -1)
00319         return RC(fcOS);
00320 
00321     done = n;
00322 
00323     return RCOK;
00324 }
00325 
00326 
00327 w_rc_t    sdisk_unix_t::pwrite(const void *buf, int count, fileoff_t pos,
00328                 int &done)
00329 {
00330     if (_fd == FD_NONE)
00331         return RC(stBADFD);
00332 
00333     int    n;
00334 
00335     n = ::os_pwrite(_fd, buf, count, pos);
00336     if (n == -1)
00337         return RC(fcOS);
00338 #if defined(USING_VALGRIND)
00339     if(RUNNING_ON_VALGRIND)
00340     {
00341         check_valgrind_errors(__LINE__, __FILE__);
00342     }
00343 #endif
00344 
00345     done = n;
00346 
00347     return RCOK;
00348 }
00349 
00350 w_rc_t    sdisk_unix_t::seek(fileoff_t pos, int origin, fileoff_t &newpos)
00351 {
00352     if (_fd == FD_NONE)
00353         return RC(stBADFD);
00354 
00355     switch (origin) {
00356     case SEEK_AT_SET:
00357         origin = SEEK_SET;
00358         break;
00359     case SEEK_AT_CUR:
00360         origin = SEEK_CUR;
00361         break;
00362     case SEEK_AT_END:
00363         origin = SEEK_END;
00364         break;
00365     }
00366 
00367     fileoff_t    l=0;
00368     l = ::os_lseek(_fd, pos, origin);
00369     if (l == -1)
00370         return RC(fcOS);
00371 
00372     newpos = l;
00373 
00374     return RCOK;
00375 }
00376 
00377 w_rc_t    sdisk_unix_t::truncate(fileoff_t size)
00378 {
00379     if (_fd == FD_NONE)
00380         return RC(stBADFD);
00381     int    n = ::os_ftruncate(_fd, size);
00382     return (n == -1) ? RC(fcOS) : RCOK;
00383 }
00384 
00385 w_rc_t    sdisk_unix_t::sync()
00386 {
00387     if (_fd == FD_NONE)
00388         return RC(stBADFD);
00389 
00390     int n = os_fsync(_fd);
00391 
00392     /* fsync's to r/o files and devices can fail ok */
00393     if (n == -1 && (errno == EBADF || errno == EINVAL))
00394         n = 0;
00395 
00396     return (n == -1) ? RC(fcOS) : RCOK;
00397 }
00398 
00399 
00400 w_rc_t    sdisk_unix_t::stat(filestat_t &st)
00401 {
00402     if (_fd == FD_NONE)
00403         return RC(stBADFD);
00404 
00405     os_stat_t    sys;
00406     int n = os_fstat(_fd, &sys);
00407     if (n == -1)
00408         return RC(fcOS);
00409 
00410     st.st_size = sys.st_size;
00411 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
00412     st.st_block_size = sys.st_blksize;
00413 #else
00414     st.st_block_size = 512;    /* XXX */
00415 #endif
00416 
00417     st.st_device_id = sys.st_dev;
00418     st.st_file_id = sys.st_ino;
00419 
00420     int mode = (sys.st_mode & S_IFMT);
00421     st.is_file = (mode == S_IFREG);
00422     st.is_dir = (mode == S_IFDIR);
00423 #ifdef S_IFBLK
00424     st.is_device = (mode == S_IFBLK);
00425 #else
00426     st.is_device = false;
00427 #endif
00428     st.is_device = st.is_device || (mode == S_IFCHR);
00429 
00430     return RCOK;
00431 }
00432 
00433 /**\endcond skip */

Generated on Wed Oct 27 08:48:36 2010 for Shore Storage Manager by  doxygen 1.4.7