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.26 2010/10/27 17:04:30 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);
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 #ifdef IOVEC_MISMATCH
00281     {
00282         struct iovec _iov[sthread_t::iovec_max];
00283         for (int i = 0; i < iovcnt; i++) {
00284             _iov[i].iov_base = (char *) iov[i].iov_base;
00285             _iov[i].iov_len = iov[i].iov_len;
00286         }
00287         n = ::os_writev(_fd, _iov, iovcnt);
00288     }
00289 #else
00290     n = ::os_writev(_fd, (const struct iovec *)iov, iovcnt);
00291 #endif
00292     if (n == -1)
00293         return RC(fcOS);
00294 
00295 #if defined(USING_VALGRIND)
00296     if(RUNNING_ON_VALGRIND)
00297     {
00298         check_valgrind_errors(__LINE__, __FILE__);
00299     }
00300 #endif
00301 
00302     done = n;
00303 
00304     return RCOK;
00305 }
00306 #endif
00307 
00308 w_rc_t    sdisk_unix_t::pread(void *buf, int count, fileoff_t pos, int &done)
00309 {
00310     if (_fd == FD_NONE)
00311         return RC(stBADFD);
00312 
00313     int    n;
00314 
00315     n = ::os_pread(_fd, buf, count, pos);
00316     if (n == -1)
00317         return RC(fcOS);
00318 
00319     done = n;
00320 
00321     return RCOK;
00322 }
00323 
00324 
00325 w_rc_t    sdisk_unix_t::pwrite(const void *buf, int count, fileoff_t pos,
00326                 int &done)
00327 {
00328     if (_fd == FD_NONE)
00329         return RC(stBADFD);
00330 
00331     int    n;
00332 
00333     n = ::os_pwrite(_fd, buf, count, pos);
00334     if (n == -1)
00335         return RC(fcOS);
00336 #if defined(USING_VALGRIND)
00337     if(RUNNING_ON_VALGRIND)
00338     {
00339         check_valgrind_errors(__LINE__, __FILE__);
00340     }
00341 #endif
00342 
00343     done = n;
00344 
00345     return RCOK;
00346 }
00347 
00348 w_rc_t    sdisk_unix_t::seek(fileoff_t pos, int origin, fileoff_t &newpos)
00349 {
00350     if (_fd == FD_NONE)
00351         return RC(stBADFD);
00352 
00353     switch (origin) {
00354     case SEEK_AT_SET:
00355         origin = SEEK_SET;
00356         break;
00357     case SEEK_AT_CUR:
00358         origin = SEEK_CUR;
00359         break;
00360     case SEEK_AT_END:
00361         origin = SEEK_END;
00362         break;
00363     }
00364 
00365     fileoff_t    l=0;
00366     l = ::os_lseek(_fd, pos, origin);
00367     if (l == -1)
00368         return RC(fcOS);
00369 
00370     newpos = l;
00371 
00372     return RCOK;
00373 }
00374 
00375 w_rc_t    sdisk_unix_t::truncate(fileoff_t size)
00376 {
00377     if (_fd == FD_NONE)
00378         return RC(stBADFD);
00379     int    n = ::os_ftruncate(_fd, size);
00380     return (n == -1) ? RC(fcOS) : RCOK;
00381 }
00382 
00383 w_rc_t    sdisk_unix_t::sync()
00384 {
00385     if (_fd == FD_NONE)
00386         return RC(stBADFD);
00387 
00388     int n = os_fsync(_fd);
00389 
00390     /* fsync's to r/o files and devices can fail ok */
00391     if (n == -1 && (errno == EBADF || errno == EINVAL))
00392         n = 0;
00393 
00394     return (n == -1) ? RC(fcOS) : RCOK;
00395 }
00396 
00397 
00398 w_rc_t    sdisk_unix_t::stat(filestat_t &st)
00399 {
00400     if (_fd == FD_NONE)
00401         return RC(stBADFD);
00402 
00403     os_stat_t    sys;
00404     int n = os_fstat(_fd, &sys);
00405     if (n == -1)
00406         return RC(fcOS);
00407 
00408     st.st_size = sys.st_size;
00409 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
00410     st.st_block_size = sys.st_blksize;
00411 #else
00412     st.st_block_size = 512;    /* XXX */
00413 #endif
00414 
00415     st.st_device_id = sys.st_dev;
00416     st.st_file_id = sys.st_ino;
00417 
00418     int mode = (sys.st_mode & S_IFMT);
00419     st.is_file = (mode == S_IFREG);
00420     st.is_dir = (mode == S_IFDIR);
00421 #ifdef S_IFBLK
00422     st.is_device = (mode == S_IFBLK);
00423 #else
00424     st.is_device = false;
00425 #endif
00426     st.is_device = st.is_device || (mode == S_IFCHR);
00427 
00428     return RCOK;
00429 }
00430 
00431 /**\endcond skip */

Generated on Mon Nov 8 11:12:38 2010 for Shore Storage Manager by  doxygen 1.4.7