Stxxl
1.4.0
|
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