Stxxl  1.4.0
io/wfs_file_base.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *  io/wfs_file_base.cpp
00003  *
00004  *  Part of the STXXL. See http://stxxl.sourceforge.net
00005  *
00006  *  Copyright (C) 2005 Roman Dementiev <dementiev@ira.uka.de>
00007  *  Copyright (C) 2008, 2010 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
00008  *  Copyright (C) 2009, 2010 Johannes Singler <singler@kit.edu>
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/wfs_file_base.h>
00016 
00017 #ifdef BOOST_MSVC
00018 
00019 __STXXL_BEGIN_NAMESPACE
00020 
00021 
00022 const char * wfs_file_base::io_type() const
00023 {
00024     return "wfs_base";
00025 }
00026 
00027 static HANDLE open_file_impl(const std::string & filename, int mode)
00028 {
00029     DWORD dwDesiredAccess = 0;
00030     DWORD dwShareMode = 0;
00031     DWORD dwCreationDisposition = 0;
00032     DWORD dwFlagsAndAttributes = 0;
00033 
00034     if (mode & file::RDONLY)
00035     {
00036         dwFlagsAndAttributes |= FILE_ATTRIBUTE_READONLY;
00037         dwDesiredAccess |= GENERIC_READ;
00038     }
00039 
00040     if (mode & file::WRONLY)
00041     {
00042         dwDesiredAccess |= GENERIC_WRITE;
00043     }
00044 
00045     if (mode & file::RDWR)
00046     {
00047         dwDesiredAccess |= (GENERIC_READ | GENERIC_WRITE);
00048     }
00049 
00050     if (mode & file::CREAT)
00051     {
00052         // ignored
00053     }
00054 
00055     if (mode & file::TRUNC)
00056     {
00057         dwCreationDisposition |= TRUNCATE_EXISTING;
00058     }
00059     else
00060     {
00061         dwCreationDisposition |= OPEN_ALWAYS;
00062     }
00063 
00064 #ifndef STXXL_DIRECT_IO_OFF
00065     if (mode & file::DIRECT)
00066     {
00067         dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
00068         // TODO: try also FILE_FLAG_WRITE_THROUGH option ?
00069     }
00070 #endif
00071 
00072     if (mode & file::SYNC)
00073     {
00074         // ignored
00075     }
00076 
00077     HANDLE file_des = ::CreateFile(filename.c_str(), dwDesiredAccess, dwShareMode, NULL,
00078                                    dwCreationDisposition, dwFlagsAndAttributes, NULL);
00079 
00080     if (file_des == INVALID_HANDLE_VALUE)
00081         stxxl_win_lasterror_exit("CreateFile  filename=" << filename, io_error);
00082 
00083     return file_des;
00084 }
00085 
00086 wfs_file_base::wfs_file_base(
00087     const std::string & filename,
00088     int mode) : file_des(INVALID_HANDLE_VALUE), mode_(mode), filename(filename), locked(false)
00089 {
00090     file_des = open_file_impl(filename, mode);
00091 
00092     if (!(mode & NO_LOCK))
00093     {
00094         lock();
00095     }
00096 
00097     if (!(mode_ & RDONLY) && (mode & DIRECT))
00098     {
00099         char buf[32768], * part;
00100         if (!GetFullPathName(filename.c_str(), sizeof(buf), buf, &part))
00101         {
00102             STXXL_ERRMSG("wfs_file_base::wfs_file_base(): GetFullPathName() error for file " << filename);
00103             bytes_per_sector = 512;
00104         }
00105         else
00106         {
00107             part[0] = char();
00108             DWORD bytes_per_sector_;
00109             if (!GetDiskFreeSpace(buf, NULL, &bytes_per_sector_, NULL, NULL))
00110             {
00111                 STXXL_ERRMSG("wfs_file_base::wfs_file_base(): GetDiskFreeSpace() error for path " << buf);
00112                 bytes_per_sector = 512;
00113             }
00114             else
00115                 bytes_per_sector = bytes_per_sector_;
00116         }
00117     }
00118 }
00119 
00120 wfs_file_base::~wfs_file_base()
00121 {
00122     close();
00123 }
00124 
00125 void wfs_file_base::close()
00126 {
00127     scoped_mutex_lock fd_lock(fd_mutex);
00128 
00129     if (file_des == INVALID_HANDLE_VALUE)
00130         return;
00131 
00132     if (!CloseHandle(file_des))
00133         stxxl_win_lasterror_exit("closing file (call of ::CloseHandle) ", io_error);
00134 
00135     file_des = INVALID_HANDLE_VALUE;
00136 }
00137 
00138 void wfs_file_base::lock()
00139 {
00140     scoped_mutex_lock fd_lock(fd_mutex);
00141     if (locked)
00142         return;  // already locked
00143     if (LockFile(file_des, 0, 0, 0xffffffff, 0xffffffff) == 0)
00144         stxxl_win_lasterror_exit("LockFile ", io_error);
00145     locked = true;
00146 }
00147 
00148 file::offset_type wfs_file_base::_size()
00149 {
00150     LARGE_INTEGER result;
00151     if (!GetFileSizeEx(file_des, &result))
00152         stxxl_win_lasterror_exit("GetFileSizeEx ", io_error);
00153 
00154     return result.QuadPart;
00155 }
00156 
00157 file::offset_type wfs_file_base::size()
00158 {
00159     scoped_mutex_lock fd_lock(fd_mutex);
00160     return _size();
00161 }
00162 
00163 void wfs_file_base::set_size(offset_type newsize)
00164 {
00165     scoped_mutex_lock fd_lock(fd_mutex);
00166     offset_type cur_size = _size();
00167 
00168     if (!(mode_ & RDONLY))
00169     {
00170         LARGE_INTEGER desired_pos;
00171         desired_pos.QuadPart = newsize;
00172 
00173         bool direct_with_bad_size = (mode_ & file::DIRECT) && (newsize % bytes_per_sector);
00174         if (direct_with_bad_size)
00175         {
00176             if (!CloseHandle(file_des))
00177                 stxxl_win_lasterror_exit("closing file (call of ::CloseHandle from set_size) ", io_error);
00178 
00179             file_des = INVALID_HANDLE_VALUE;
00180             file_des = open_file_impl(filename, WRONLY);
00181         }
00182 
00183         if (!SetFilePointerEx(file_des, desired_pos, NULL, FILE_BEGIN))
00184             stxxl_win_lasterror_exit("SetFilePointerEx in wfs_file_base::set_size(..) oldsize=" << cur_size <<
00185                                      " newsize=" << newsize << " ", io_error);
00186 
00187         if (!SetEndOfFile(file_des))
00188             stxxl_win_lasterror_exit("SetEndOfFile oldsize=" << cur_size <<
00189                                      " newsize=" << newsize << " ", io_error);
00190 
00191         if (direct_with_bad_size)
00192         {
00193             if (!CloseHandle(file_des))
00194                 stxxl_win_lasterror_exit("closing file (call of ::CloseHandle from set_size) ", io_error);
00195 
00196             file_des = INVALID_HANDLE_VALUE;
00197             file_des = open_file_impl(filename, mode_ & ~TRUNC);
00198         }
00199     }
00200 }
00201 
00202 void wfs_file_base::remove()
00203 {
00204     close();
00205     ::DeleteFile(filename.c_str());
00206 }
00207 
00208 __STXXL_END_NAMESPACE
00209 
00210 #endif // #ifdef BOOST_MSVC
00211 // vim: et:ts=4:sw=4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines