STXXL  1.4.1
 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 const char* wfs_file_base::io_type() const
28 {
29  return "wfs_base";
30 }
31 
32 static HANDLE open_file_impl(const std::string& filename, int mode)
33 {
34  DWORD dwDesiredAccess = 0;
35  DWORD dwShareMode = 0;
36  DWORD dwCreationDisposition = 0;
37  DWORD dwFlagsAndAttributes = 0;
38 
39  if (mode & file::RDONLY)
40  {
41  dwFlagsAndAttributes |= FILE_ATTRIBUTE_READONLY;
42  dwDesiredAccess |= GENERIC_READ;
43  }
44 
45  if (mode & file::WRONLY)
46  {
47  dwDesiredAccess |= GENERIC_WRITE;
48  }
49 
50  if (mode & file::RDWR)
51  {
52  dwDesiredAccess |= (GENERIC_READ | GENERIC_WRITE);
53  }
54 
55  if (mode & file::CREAT)
56  {
57  // ignored
58  }
59 
60  if (mode & file::TRUNC)
61  {
62  dwCreationDisposition |= TRUNCATE_EXISTING;
63  }
64  else
65  {
66  dwCreationDisposition |= OPEN_ALWAYS;
67  }
68 
69  if (mode & file::DIRECT)
70  {
71 #if !STXXL_DIRECT_IO_OFF
72  dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
73  // TODO: try also FILE_FLAG_WRITE_THROUGH option ?
74 #else
75  if (mode & file::REQUIRE_DIRECT) {
76  STXXL_ERRMSG("Error: open()ing " << filename << " with DIRECT mode required, but the system does not support it.");
77  return INVALID_HANDLE_VALUE;
78  }
79  else {
80  STXXL_MSG("Warning: open()ing " << filename << " without DIRECT mode, as the system does not support it.");
81  }
82 #endif
83  }
84 
85  if (mode & file::SYNC)
86  {
87  // ignored
88  }
89 
90  HANDLE file_des = ::CreateFile(filename.c_str(), dwDesiredAccess, dwShareMode, NULL,
91  dwCreationDisposition, dwFlagsAndAttributes, NULL);
92 
93  if (file_des != INVALID_HANDLE_VALUE)
94  return file_des;
95 
96 #if !STXXL_DIRECT_IO_OFF
97  if ((mode& file::DIRECT) && !(mode & file::REQUIRE_DIRECT))
98  {
99  STXXL_MSG("CreateFile() error on path=" << filename << " mode=" << mode << ", retrying without DIRECT mode.");
100 
101  dwFlagsAndAttributes &= ~FILE_FLAG_NO_BUFFERING;
102 
103  HANDLE file_des = ::CreateFile(filename.c_str(), dwDesiredAccess, dwShareMode, NULL,
104  dwCreationDisposition, dwFlagsAndAttributes, NULL);
105 
106  if (file_des != INVALID_HANDLE_VALUE)
107  return file_des;
108  }
109 #endif
110 
111  STXXL_THROW_WIN_LASTERROR(io_error, "CreateFile() path=" << filename << " mode=" << mode);
112 }
113 
114 wfs_file_base::wfs_file_base(
115  const std::string& filename,
116  int mode) : file_des(INVALID_HANDLE_VALUE), mode_(mode), filename(filename), locked(false)
117 {
118  file_des = open_file_impl(filename, mode);
119 
120  if (!(mode & NO_LOCK))
121  {
122  lock();
123  }
124 
125  if (!(mode_ & RDONLY) && (mode & DIRECT))
126  {
127  char buf[32768], * part;
128  if (!GetFullPathName(filename.c_str(), sizeof(buf), buf, &part))
129  {
130  STXXL_ERRMSG("wfs_file_base::wfs_file_base(): GetFullPathName() error for file " << filename);
131  bytes_per_sector = 512;
132  }
133  else
134  {
135  part[0] = char();
136  DWORD bytes_per_sector_;
137  if (!GetDiskFreeSpace(buf, NULL, &bytes_per_sector_, NULL, NULL))
138  {
139  STXXL_ERRMSG("wfs_file_base::wfs_file_base(): GetDiskFreeSpace() error for path " << buf);
140  bytes_per_sector = 512;
141  }
142  else
143  bytes_per_sector = bytes_per_sector_;
144  }
145  }
146 }
147 
149 {
150  close();
151 }
152 
154 {
155  scoped_mutex_lock fd_lock(fd_mutex);
156 
157  if (file_des == INVALID_HANDLE_VALUE)
158  return;
159 
160  if (!CloseHandle(file_des))
161  STXXL_THROW_WIN_LASTERROR(io_error, "CloseHandle() of file fd=" << file_des);
162 
163  file_des = INVALID_HANDLE_VALUE;
164 }
165 
167 {
168  scoped_mutex_lock fd_lock(fd_mutex);
169  if (locked)
170  return; // already locked
171  if (LockFile(file_des, 0, 0, 0xffffffff, 0xffffffff) == 0)
172  STXXL_THROW_WIN_LASTERROR(io_error, "LockFile() fd=" << file_des);
173  locked = true;
174 }
175 
177 {
178  LARGE_INTEGER result;
179  if (!GetFileSizeEx(file_des, &result))
180  STXXL_THROW_WIN_LASTERROR(io_error, "GetFileSizeEx() fd=" << file_des);
181 
182  return result.QuadPart;
183 }
184 
186 {
187  scoped_mutex_lock fd_lock(fd_mutex);
188  return _size();
189 }
190 
191 void wfs_file_base::set_size(offset_type newsize)
192 {
193  scoped_mutex_lock fd_lock(fd_mutex);
194  offset_type cur_size = _size();
195 
196  if (!(mode_ & RDONLY))
197  {
198  LARGE_INTEGER desired_pos;
199  desired_pos.QuadPart = newsize;
200 
201  bool direct_with_bad_size = (mode_& file::DIRECT) && (newsize % bytes_per_sector);
202  if (direct_with_bad_size)
203  {
204  if (!CloseHandle(file_des))
205  STXXL_THROW_WIN_LASTERROR(io_error, "closing file (call of ::CloseHandle() from set_size) ");
206 
207  file_des = INVALID_HANDLE_VALUE;
209  }
210 
211  if (!SetFilePointerEx(file_des, desired_pos, NULL, FILE_BEGIN))
213  "SetFilePointerEx() in wfs_file_base::set_size(..) oldsize=" << cur_size <<
214  " newsize=" << newsize << " ");
215 
216  if (!SetEndOfFile(file_des))
217  STXXL_THROW_WIN_LASTERROR(io_error, "SetEndOfFile() oldsize=" << cur_size <<
218  " newsize=" << newsize << " ");
219 
220  if (direct_with_bad_size)
221  {
222  if (!CloseHandle(file_des))
223  STXXL_THROW_WIN_LASTERROR(io_error, "closing file (call of ::CloseHandle() from set_size) ");
224 
225  file_des = INVALID_HANDLE_VALUE;
227  }
228  }
229 }
230 
232 {
233  close();
234  ::DeleteFile(filename.c_str());
235 }
236 
238 
239 #endif // STXXL_WINDOWS
240 // vim: et:ts=4:sw=4
const std::string filename
Definition: wfs_file_base.h:41
I/Os proceed bypassing file system buffers, i.e.
Definition: file.h:74
only writing of the file is allowed
Definition: file.h:71
do not acquire an exclusive lock by default
Definition: file.h:78
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:70
void close_remove()
close and remove file
offset_type bytes_per_sector
Definition: wfs_file_base.h:42
Aquire a lock that&#39;s valid until the end of scope.
Definition: mutex.h:105
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
#define STXXL_ERRMSG(x)
Definition: verbose.h:80
once file is opened its length becomes zero
Definition: file.h:76
#define STXXL_MSG(x)
Definition: verbose.h:73
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:60
static HANDLE open_file_impl(const std::string &filename, int mode)
#define STXXL_END_NAMESPACE
Definition: namespace.h:17