Stxxl  1.4.0
io/boostfd_file.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *  io/boostfd_file.cpp
00003  *
00004  *  Part of the STXXL. See http://stxxl.sourceforge.net
00005  *
00006  *  Copyright (C) 2006 Roman Dementiev <dementiev@ira.uka.de>
00007  *  Copyright (C) 2009, 2010 Johannes Singler <singler@kit.edu>
00008  *  Copyright (C) 2008, 2010 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
00009  *
00010  *  Distributed under the Boost Software License, Version 1.0.
00011  *  (See accompanying file LICENSE_1_0.txt or copy at
00012  *  http://www.boost.org/LICENSE_1_0.txt)
00013  **************************************************************************/
00014 
00015 #include <stxxl/bits/io/boostfd_file.h>
00016 
00017 #if STXXL_HAVE_BOOSTFD_FILE
00018 
00019 #include <stxxl/bits/io/iostats.h>
00020 #include <stxxl/bits/common/error_handling.h>
00021 
00022 #include <boost/filesystem/operations.hpp>
00023 #include <boost/filesystem/fstream.hpp>
00024 #include <boost/version.hpp>
00025 
00026 
00027 __STXXL_BEGIN_NAMESPACE
00028 
00029 
00030 void boostfd_file::serve(const request * req) throw (io_error)
00031 {
00032     scoped_mutex_lock fd_lock(fd_mutex);
00033     assert(req->get_file() == this);
00034     offset_type offset = req->get_offset();
00035     void * buffer = req->get_buffer();
00036     size_type bytes = req->get_size();
00037     request::request_type type = req->get_type();
00038 
00039     try
00040     {
00041         file_des.seek(offset, BOOST_IOS::beg);
00042     }
00043     catch (const std::exception & ex)
00044     {
00045         STXXL_THROW2(io_error,
00046                      "Error doing seek() in boostfd_request::serve()" <<
00047                      " offset=" << offset <<
00048                      " this=" << this <<
00049                      " buffer=" << buffer <<
00050                      " bytes=" << bytes <<
00051                      " type=" << ((type == request::READ) ? "READ" : "WRITE") <<
00052                      " : " << ex.what());
00053     }
00054 
00055     stats::scoped_read_write_timer read_write_timer(bytes, type == request::WRITE);
00056 
00057     if (type == request::READ)
00058     {
00059         try
00060         {
00061             std::streamsize rc = file_des.read((char *)buffer, bytes);
00062             if (rc != std::streamsize(bytes)) {
00063                 STXXL_THROW2(io_error, " partial read: missing " << (bytes - rc) << " out of " << bytes << " bytes");
00064             }
00065         }
00066         catch (const std::exception & ex)
00067         {
00068             STXXL_THROW2(io_error,
00069                          "Error doing read() in boostfd_request::serve()" <<
00070                          " offset=" << offset <<
00071                          " this=" << this <<
00072                          " buffer=" << buffer <<
00073                          " bytes=" << bytes <<
00074                          " type=" << ((type == request::READ) ? "READ" : "WRITE") <<
00075                          " : " << ex.what());
00076         }
00077     }
00078     else
00079     {
00080         try
00081         {
00082             std::streamsize rc = file_des.write((char *)buffer, bytes);
00083             if (rc != std::streamsize(bytes)) {
00084                 STXXL_THROW2(io_error, " partial read: missing " << (bytes - rc) << " out of " << bytes << " bytes");
00085             }
00086         }
00087         catch (const std::exception & ex)
00088         {
00089             STXXL_THROW2(io_error,
00090                          "Error doing write() in boostfd_request::serve()" <<
00091                          " offset=" << offset <<
00092                          " this=" << this <<
00093                          " buffer=" << buffer <<
00094                          " bytes=" << bytes <<
00095                          " type=" << ((type == request::READ) ? "READ" : "WRITE") <<
00096                          " : " << ex.what());
00097         }
00098     }
00099 }
00100 
00101 const char * boostfd_file::io_type() const
00102 {
00103     return "boostfd";
00104 }
00105 
00106 boostfd_file::boostfd_file(
00107     const std::string & filename,
00108     int mode,
00109     int queue_id, int allocator_id) : disk_queued_file(queue_id, allocator_id), mode_(mode)
00110 {
00111     BOOST_IOS::openmode boostfd_mode;
00112 
00113     if (mode & RDONLY)
00114     {
00115         boostfd_mode = BOOST_IOS::in;
00116     }
00117 
00118     if (mode & WRONLY)
00119     {
00120         boostfd_mode = BOOST_IOS::out;
00121     }
00122 
00123     if (mode & RDWR)
00124     {
00125         boostfd_mode = BOOST_IOS::out | BOOST_IOS::in;
00126     }
00127 
00128 #if defined(BOOST_FILESYSTEM_VERSION) && (BOOST_FILESYSTEM_VERSION >= 3)
00129     const boost::filesystem::path fspath(filename);
00130 #else
00131     const boost::filesystem::path fspath(filename,
00132                                          boost::filesystem::native);
00133 #endif
00134 
00135     if (mode & TRUNC)
00136     {
00137         if (boost::filesystem::exists(fspath))
00138         {
00139             boost::filesystem::remove(fspath);
00140             boost::filesystem::ofstream f(fspath);
00141             f.close();
00142             assert(boost::filesystem::exists(fspath));
00143         }
00144     }
00145 
00146     if (mode & CREAT)
00147     {
00148         // need to be emulated:
00149         if (!boost::filesystem::exists(fspath))
00150         {
00151             boost::filesystem::ofstream f(fspath);
00152             f.close();
00153             assert(boost::filesystem::exists(fspath));
00154         }
00155     }
00156 
00157  #ifndef STXXL_DIRECT_IO_OFF
00158     if (mode & DIRECT)
00159     {
00160         // direct mode not supported in Boost
00161     }
00162  #endif
00163 
00164     if (mode & SYNC)
00165     {
00166         // ???
00167     }
00168 
00169 #if (BOOST_VERSION >= 104100)
00170     file_des.open(filename, boostfd_mode);      // also compiles with earlier Boost versions, but differs semantically
00171 #else
00172     file_des.open(filename, boostfd_mode, boostfd_mode);
00173 #endif
00174 }
00175 
00176 boostfd_file::~boostfd_file()
00177 {
00178     scoped_mutex_lock fd_lock(fd_mutex);
00179     file_des.close();
00180 }
00181 
00182 inline file::offset_type boostfd_file::_size()
00183 {
00184     return file_des.seek(0, BOOST_IOS::end);
00185 }
00186 
00187 file::offset_type boostfd_file::size()
00188 {
00189     scoped_mutex_lock fd_lock(fd_mutex);
00190     return _size();
00191 }
00192 
00193 void boostfd_file::set_size(offset_type newsize)
00194 {
00195     scoped_mutex_lock fd_lock(fd_mutex);
00196     offset_type oldsize = _size();
00197     file_des.seek(newsize, BOOST_IOS::beg);
00198     file_des.seek(0, BOOST_IOS::beg); // not important ?
00199     assert(_size() >= oldsize);
00200 }
00201 
00202 void boostfd_file::lock()
00203 {
00204     // FIXME: is there no locking possible/needed/... for boostfd?
00205 }
00206 
00207 __STXXL_END_NAMESPACE
00208 
00209 #endif  // #if STXXL_HAVE_BOOSTFD_FILE
00210 // vim: et:ts=4:sw=4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines