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.28 2012/01/02 17:02:22 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 
00101 int    sdisk_unix_t::convert_flags(int sflags)
00102 {
00103     int    flags = 0;
00104 
00105     /* 1 of n */
00106     switch (modeBits(sflags)) {
00107     case OPEN_RDWR:
00108         flags |= O_RDWR;
00109         break;
00110     case OPEN_WRONLY:
00111         flags |= O_WRONLY;
00112         break;
00113     case OPEN_RDONLY:
00114         flags |= O_RDONLY;
00115         break;
00116     }
00117 
00118     /* m of n */
00119     /* could make a data driven flag conversion, :-) */
00120     if (hasOption(sflags, OPEN_CREATE))
00121         flags |= O_CREAT;
00122     if (hasOption(sflags, OPEN_TRUNC))
00123         flags |= O_TRUNC;
00124     if (hasOption(sflags, OPEN_EXCL))
00125         flags |= O_EXCL;
00126 #ifdef O_SYNC
00127     if (hasOption(sflags, OPEN_SYNC))
00128         flags |= O_SYNC;
00129 #endif
00130     if (hasOption(sflags, OPEN_APPEND))
00131         flags |= O_APPEND;
00132 #ifdef O_DIRECT
00133     /*
00134      * From the open man page:
00135      *      O_DIRECT
00136               Try to minimize cache effects of the I/O to and from this  file.
00137               In  general  this  will degrade performance, but it is useful in
00138               special situations, such  as  when  applications  do  their  own
00139               caching.   File I/O is done directly to/from user space buffers.
00140               The I/O is synchronous, i.e., at the completion of a read(2)  or
00141               write(2),  data  is  guaranteed to have been transferred.  Under
00142               Linux 2.4 transfer sizes, and the alignment of user  buffer  and
00143               file  offset  must all be multiples of the logical block size of
00144               the file system. Under Linux 2.6 alignment must  fit  the  block
00145               size of the device.
00146     */
00147     if (hasOption(sflags, OPEN_RAW))
00148         flags |= O_DIRECT;
00149 #endif
00150 
00151     return flags;
00152 }
00153 
00154 
00155 sdisk_unix_t::~sdisk_unix_t()
00156 {
00157     if (_fd != FD_NONE)
00158         W_COERCE(close());
00159 }
00160 
00161 
00162 w_rc_t    sdisk_unix_t::make(const char *name, int flags, int mode,
00163                sdisk_t *&disk)
00164 {
00165     sdisk_unix_t    *ud;
00166     w_rc_t        e;
00167 
00168     disk = 0;    /* default value*/
00169     
00170     ud = new sdisk_unix_t(name);
00171     if (!ud)
00172         return RC(fcOUTOFMEMORY);
00173 
00174     e = ud->open(name, flags, mode);
00175     if (e.is_error()) {
00176         delete ud;
00177         return e;
00178     }
00179 
00180     disk = ud;
00181     return RCOK;
00182 }
00183 
00184 
00185 w_rc_t    sdisk_unix_t::open(const char *name, int flags, int mode)
00186 {
00187     if (_fd != FD_NONE)
00188         return RC(stBADFD);    /* XXX in use */
00189 
00190     _fd = ::os_open(name, convert_flags(flags), mode);
00191     if (_fd == -1) {
00192         w_rc_t rc = RC(fcOS);
00193         RC_APPEND_MSG(rc, << "Offending file: " << name << " mode " << mode);
00194         return rc;
00195     }
00196 
00197     return RCOK;
00198 }
00199 
00200 w_rc_t    sdisk_unix_t::close()
00201 {
00202     if (_fd == FD_NONE)
00203         return RC(stBADFD);    /* XXX closed */
00204 
00205     int    n;
00206 
00207     n = ::os_close(_fd);
00208     if (n == -1)
00209         return RC(fcOS);
00210 
00211     _fd = FD_NONE;
00212     return RCOK;
00213 }
00214 
00215 
00216 
00217 
00218 w_rc_t    sdisk_unix_t::read(void *buf, int count, int &done)
00219 {
00220     if (_fd == FD_NONE)
00221         return RC(stBADFD);
00222 
00223     int    n;
00224     n = ::os_read(_fd, buf, count);
00225     if (n == -1)
00226         return RC(fcOS);
00227 
00228     done = n;
00229 
00230     return RCOK;
00231 }
00232 
00233 w_rc_t    sdisk_unix_t::write(const void *buf, int count, int &done)
00234 {
00235     if (_fd == FD_NONE)
00236         return RC(stBADFD);
00237 
00238     int    n;
00239 
00240     n = ::os_write(_fd, buf, count);
00241     if (n == -1)
00242         return RC(fcOS);
00243 
00244 #if defined(USING_VALGRIND)
00245     if(RUNNING_ON_VALGRIND)
00246     {
00247         check_valgrind_errors(__LINE__, __FILE__);
00248     }
00249 #endif
00250 
00251     done = n;
00252 
00253     return RCOK;
00254 }
00255 
00256 #ifdef HAVE_IO_VECTOR
00257 w_rc_t    sdisk_unix_t::readv(const iovec_t *iov, int iovcnt, int &done)
00258 {
00259     if (_fd == FD_NONE)
00260         return RC(stBADFD);
00261 
00262     int    n;
00263 
00264     n = ::os_readv(_fd, (const struct iovec *)iov, iovcnt);
00265     if (n == -1)
00266         return RC(fcOS);
00267 
00268     done = n;
00269 
00270     return RCOK;
00271 }
00272 
00273 w_rc_t    sdisk_unix_t::writev(const iovec_t *iov, int iovcnt, int &done)
00274 {
00275     if (_fd == FD_NONE)
00276         return RC(stBADFD);
00277 
00278     int    n;
00279 
00280     n = ::os_writev(_fd, (const struct iovec *)iov, iovcnt);
00281     if (n == -1)
00282         return RC(fcOS);
00283 
00284 #if defined(USING_VALGRIND)
00285     if(RUNNING_ON_VALGRIND)
00286     {
00287         check_valgrind_errors(__LINE__, __FILE__);
00288     }
00289 #endif
00290 
00291     done = n;
00292 
00293     return RCOK;
00294 }
00295 #endif
00296 
00297 w_rc_t    sdisk_unix_t::pread(void *buf, int count, fileoff_t pos, int &done)
00298 {
00299     if (_fd == FD_NONE)
00300         return RC(stBADFD);
00301 
00302     int    n;
00303 
00304     n = ::os_pread(_fd, buf, count, pos);
00305     if (n == -1)
00306         return RC(fcOS);
00307 
00308     done = n;
00309 
00310     return RCOK;
00311 }
00312 
00313 
00314 w_rc_t    sdisk_unix_t::pwrite(const void *buf, int count, fileoff_t pos,
00315                 int &done)
00316 {
00317     if (_fd == FD_NONE)
00318         return RC(stBADFD);
00319 
00320     int    n;
00321 
00322     n = ::os_pwrite(_fd, buf, count, pos);
00323     if (n == -1)
00324         return RC(fcOS);
00325 #if defined(USING_VALGRIND)
00326     if(RUNNING_ON_VALGRIND)
00327     {
00328         check_valgrind_errors(__LINE__, __FILE__);
00329     }
00330 #endif
00331 
00332     done = n;
00333 
00334     return RCOK;
00335 }
00336 
00337 w_rc_t    sdisk_unix_t::seek(fileoff_t pos, int origin, fileoff_t &newpos)
00338 {
00339     if (_fd == FD_NONE)
00340         return RC(stBADFD);
00341 
00342     switch (origin) {
00343     case SEEK_AT_SET:
00344         origin = SEEK_SET;
00345         break;
00346     case SEEK_AT_CUR:
00347         origin = SEEK_CUR;
00348         break;
00349     case SEEK_AT_END:
00350         origin = SEEK_END;
00351         break;
00352     }
00353 
00354     fileoff_t    l=0;
00355     l = ::os_lseek(_fd, pos, origin);
00356     if (l == -1)
00357         return RC(fcOS);
00358 
00359     newpos = l;
00360 
00361     return RCOK;
00362 }
00363 
00364 w_rc_t    sdisk_unix_t::truncate(fileoff_t size)
00365 {
00366     if (_fd == FD_NONE)
00367         return RC(stBADFD);
00368     int    n = ::os_ftruncate(_fd, size);
00369     return (n == -1) ? RC(fcOS) : RCOK;
00370 }
00371 
00372 w_rc_t    sdisk_unix_t::sync()
00373 {
00374     if (_fd == FD_NONE)
00375         return RC(stBADFD);
00376 
00377     int n = os_fsync(_fd);
00378 
00379     /* fsync's to r/o files and devices can fail ok */
00380     if (n == -1 && (errno == EBADF || errno == EINVAL))
00381         n = 0;
00382 
00383     return (n == -1) ? RC(fcOS) : RCOK;
00384 }
00385 
00386 
00387 w_rc_t    sdisk_unix_t::stat(filestat_t &st)
00388 {
00389     if (_fd == FD_NONE)
00390         return RC(stBADFD);
00391 
00392     os_stat_t    sys;
00393     int n = os_fstat(_fd, &sys);
00394     if (n == -1)
00395         return RC(fcOS);
00396 
00397     st.st_size = sys.st_size;
00398 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
00399     st.st_block_size = sys.st_blksize;
00400 #else
00401     st.st_block_size = 512;    /* XXX */
00402 #endif
00403 
00404     st.st_device_id = sys.st_dev;
00405     st.st_file_id = sys.st_ino;
00406 
00407     int mode = (sys.st_mode & S_IFMT);
00408     st.is_file = (mode == S_IFREG);
00409     st.is_dir = (mode == S_IFDIR);
00410 #ifdef S_IFBLK
00411     st.is_device = (mode == S_IFBLK);
00412 #else
00413     st.is_device = false;
00414 #endif
00415     st.is_device = st.is_device || (mode == S_IFCHR);
00416 
00417     return RCOK;
00418 }
00419 
00420 /**\endcond skip */

Generated on Mon Jan 2 15:13:57 2012 for Shore Storage Manager by  doxygen 1.4.7