STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
wfs_file_base.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * lib/io/wfs_file_base.cpp
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2005 Roman Dementiev <[email protected]>
7  * Copyright (C) 2008, 2010 Andreas Beckmann <[email protected]>
8  * Copyright (C) 2009, 2010 Johannes Singler <[email protected]>
9  *
10  * Distributed under the Boost Software License, Version 1.0.
11  * (See accompanying file LICENSE_1_0.txt or copy at
12  * http://www.boost.org/LICENSE_1_0.txt)
13  **************************************************************************/
14 
17 
18 #if STXXL_WINDOWS
19 
20 #ifndef NOMINMAX
21  #define NOMINMAX
22 #endif
23 #include <windows.h>
24 
26 
27 
28 const char* wfs_file_base::io_type() const
29 {
30  return "wfs_base";
31 }
32 
33 static HANDLE open_file_impl(const std::string& filename, int mode)
34 {
35  DWORD dwDesiredAccess = 0;
36  DWORD dwShareMode = 0;
37  DWORD dwCreationDisposition = 0;
38  DWORD dwFlagsAndAttributes = 0;
39 
40  if (mode & file::RDONLY)
41  {
42  dwFlagsAndAttributes |= FILE_ATTRIBUTE_READONLY;
43  dwDesiredAccess |= GENERIC_READ;
44  }
45 
46  if (mode & file::WRONLY)
47  {
48  dwDesiredAccess |= GENERIC_WRITE;
49  }
50 
51  if (mode & file::RDWR)
52  {
53  dwDesiredAccess |= (GENERIC_READ | GENERIC_WRITE);
54  }
55 
56  if (mode & file::CREAT)
57  {
58  // ignored
59  }
60 
61  if (mode & file::TRUNC)
62  {
63  dwCreationDisposition |= TRUNCATE_EXISTING;
64  }
65  else
66  {
67  dwCreationDisposition |= OPEN_ALWAYS;
68  }
69 
70  if (mode & file::DIRECT)
71  {
72 #if !STXXL_DIRECT_IO_OFF
73  dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
74  // TODO: try also FILE_FLAG_WRITE_THROUGH option ?
75 #else
76  if (mode & file::REQUIRE_DIRECT) {
77  STXXL_ERRMSG("Error: open()ing " << filename << " with DIRECT mode required, but the system does not support it.");
78  file_des = INVALID_HANDLE_VALUE;
79  return;
80  }
81  else {
82  STXXL_MSG("Warning: open()ing " << filename << " without DIRECT mode, as the system does not support it.");
83  }
84 #endif
85  }
86 
87  if (mode & file::SYNC)
88  {
89  // ignored
90  }
91 
92  HANDLE file_des = ::CreateFile(filename.c_str(), dwDesiredAccess, dwShareMode, NULL,
93  dwCreationDisposition, dwFlagsAndAttributes, NULL);
94 
95  if (file_des != INVALID_HANDLE_VALUE)
96  return file_des;
97 
98 #if !STXXL_DIRECT_IO_OFF
99  if ((mode& file::DIRECT) && !(mode & file::REQUIRE_DIRECT))
100  {
101  STXXL_MSG("CreateFile() error on path=" << filename << " mode=" << mode << ", retrying without DIRECT mode.");
102 
103  dwFlagsAndAttributes &= ~FILE_FLAG_NO_BUFFERING;
104 
105  HANDLE file_des = ::CreateFile(filename.c_str(), dwDesiredAccess, dwShareMode, NULL,
106  dwCreationDisposition, dwFlagsAndAttributes, NULL);
107 
108  if (file_des != INVALID_HANDLE_VALUE)
109  return file_des;
110  }
111 #endif
112 
113  STXXL_THROW_WIN_LASTERROR(io_error, "CreateFile() path=" << filename << " mode=" << mode);
114 }
115 
116 wfs_file_base::wfs_file_base(
117  const std::string& filename,
118  int mode) : file_des(INVALID_HANDLE_VALUE), mode_(mode), filename(filename), locked(false)
119 {
120  file_des = open_file_impl(filename, mode);
121 
122  if (!(mode & NO_LOCK))
123  {
124  lock();
125  }
126 
127  if (!(mode_ & RDONLY) && (mode & DIRECT))
128  {
129  char buf[32768], * part;
130  if (!GetFullPathName(filename.c_str(), sizeof(buf), buf, &part))
131  {
132  STXXL_ERRMSG("wfs_file_base::wfs_file_base(): GetFullPathName() error for file " << filename);
133  bytes_per_sector = 512;
134  }
135  else
136  {
137  part[0] = char();
138  DWORD bytes_per_sector_;
139  if (!GetDiskFreeSpace(buf, NULL, &bytes_per_sector_, NULL, NULL))
140  {
141  STXXL_ERRMSG("wfs_file_base::wfs_file_base(): GetDiskFreeSpace() error for path " << buf);
142  bytes_per_sector = 512;
143  }
144  else
145  bytes_per_sector = bytes_per_sector_;
146  }
147  }
148 }
149 
151 {
152  close();
153 }
154 
156 {
157  scoped_mutex_lock fd_lock(fd_mutex);
158 
159  if (file_des == INVALID_HANDLE_VALUE)
160  return;
161 
162  if (!CloseHandle(file_des))
163  STXXL_THROW_WIN_LASTERROR(io_error, "CloseHandle() of file fd=" << file_des);
164 
165  file_des = INVALID_HANDLE_VALUE;
166 }
167 
169 {
170  scoped_mutex_lock fd_lock(fd_mutex);
171  if (locked)
172  return; // already locked
173  if (LockFile(file_des, 0, 0, 0xffffffff, 0xffffffff) == 0)
174  STXXL_THROW_WIN_LASTERROR(io_error, "LockFile() fd=" << file_des);
175  locked = true;
176 }
177 
179 {
180  LARGE_INTEGER result;
181  if (!GetFileSizeEx(file_des, &result))
182  STXXL_THROW_WIN_LASTERROR(io_error, "GetFileSizeEx() fd=" << file_des);
183 
184  return result.QuadPart;
185 }
186 
188 {
189  scoped_mutex_lock fd_lock(fd_mutex);
190  return _size();
191 }
192 
193 void wfs_file_base::set_size(offset_type newsize)
194 {
195  scoped_mutex_lock fd_lock(fd_mutex);
196  offset_type cur_size = _size();
197 
198  if (!(mode_ & RDONLY))
199  {
200  LARGE_INTEGER desired_pos;
201  desired_pos.QuadPart = newsize;
202 
203  bool direct_with_bad_size = (mode_& file::DIRECT) && (newsize % bytes_per_sector);
204  if (direct_with_bad_size)
205  {
206  if (!CloseHandle(file_des))
207  STXXL_THROW_WIN_LASTERROR(io_error, "closing file (call of ::CloseHandle() from set_size) ");
208 
209  file_des = INVALID_HANDLE_VALUE;
211  }
212 
213  if (!SetFilePointerEx(file_des, desired_pos, NULL, FILE_BEGIN))
215  "SetFilePointerEx() in wfs_file_base::set_size(..) oldsize=" << cur_size <<
216  " newsize=" << newsize << " ");
217 
218  if (!SetEndOfFile(file_des))
219  STXXL_THROW_WIN_LASTERROR(io_error, "SetEndOfFile() oldsize=" << cur_size <<
220  " newsize=" << newsize << " ");
221 
222  if (direct_with_bad_size)
223  {
224  if (!CloseHandle(file_des))
225  STXXL_THROW_WIN_LASTERROR(io_error, "closing file (call of ::CloseHandle() from set_size) ");
226 
227  file_des = INVALID_HANDLE_VALUE;
229  }
230  }
231 }
232 
234 {
235  close();
236  ::DeleteFile(filename.c_str());
237 }
238 
240 
241 #endif // STXXL_WINDOWS
242 // vim: et:ts=4:sw=4
const std::string filename
Definition: wfs_file_base.h:42
I/Os proceed bypassing file system buffers, i.e.
Definition: file.h:78
only writing of the file is allowed
Definition: file.h:75
do not aquire an exclusive lock by default
Definition: file.h:82
void lock()
Locks file for reading and writing (acquires a lock in the file system).
#define STXXL_THROW_WIN_LASTERROR(exception_type, error_message)
Throws exception_type with &quot;Error in [function] : [error_message] : [formatted GetLastError()]&quot;.
only reading of the file is allowed
Definition: file.h:74
void close_remove()
close and remove file
offset_type bytes_per_sector
Definition: wfs_file_base.h:43
Aquire a lock that&#39;s valid until the end of scope.
Definition: mutex.h:106
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
#define STXXL_ERRMSG(x)
Definition: verbose.h:79
once file is opened its length becomes zero
Definition: file.h:80
#define STXXL_MSG(x)
Definition: verbose.h:72
void set_size(offset_type newsize)
offset_type size()
Returns size of the file.
request::offset_type offset_type
the offset of a request, also the size of the file
Definition: file.h:64
static HANDLE open_file_impl(const std::string &filename, int mode)
#define STXXL_END_NAMESPACE
Definition: namespace.h:17