Joedb 9.1.4
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Windows_File.cpp
Go to the documentation of this file.
3
4#include <algorithm>
5#include <cctype>
6
7namespace joedb
8{
9 const std::array<DWORD, Windows_Handle::mode_count> Windows_Handle::desired_access
10 {
11 GENERIC_READ,
12 GENERIC_READ | GENERIC_WRITE,
13 GENERIC_READ | GENERIC_WRITE,
14 GENERIC_READ | GENERIC_WRITE,
15 GENERIC_READ | GENERIC_WRITE,
16 GENERIC_READ | GENERIC_WRITE
17 };
18
19 const std::array<DWORD, Windows_Handle::mode_count> Windows_Handle::share_mode
20 {
21 FILE_SHARE_READ | FILE_SHARE_WRITE,
22 FILE_SHARE_READ,
23 FILE_SHARE_READ,
24 FILE_SHARE_READ,
25 FILE_SHARE_READ | FILE_SHARE_WRITE,
26 FILE_SHARE_READ | FILE_SHARE_WRITE
27 };
28
29 const std::array<DWORD, Windows_Handle::mode_count> Windows_Handle::creation_disposition
30 {
31 OPEN_EXISTING,
32 OPEN_EXISTING,
33 CREATE_NEW,
34 OPEN_ALWAYS,
35 OPEN_ALWAYS,
36 OPEN_ALWAYS
37 };
38
39 /////////////////////////////////////////////////////////////////////////////
40 static DWORD size_to_dword(size_t size)
41 /////////////////////////////////////////////////////////////////////////////
42 {
43 return DWORD(std::min(size, size_t(1ULL << 31)));
44 }
45
46 /////////////////////////////////////////////////////////////////////////////
47 void Windows_Handle::throw_last_error
48 /////////////////////////////////////////////////////////////////////////////
49 (
50 const char *action,
51 const char *file_name
52 )
53 {
54 const DWORD last_error = GetLastError();
55 LPVOID buffer;
56
57 FormatMessage
58 (
59 FORMAT_MESSAGE_ALLOCATE_BUFFER |
60 FORMAT_MESSAGE_FROM_SYSTEM,
61 NULL,
62 last_error,
63 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
64 (LPTSTR)&buffer,
65 0,
66 NULL
67 );
68
69 std::string error((const char *)buffer);
70 LocalFree(buffer);
71 while (!error.empty() && std::isspace(error.back()))
72 error.pop_back();
73
74 throw Exception
75 (
76 std::string(action) + ' ' + std::string(file_name) + ": " + error
77 );
78 }
79
80 /////////////////////////////////////////////////////////////////////////////
81 BOOL Windows_Handle::lock(Lock_Operation op, int64_t start, int64_t size)
82 /////////////////////////////////////////////////////////////////////////////
83 {
84 if (start < 0 || size < 0)
85 return FALSE;
86
89
90 large_start.QuadPart = uint64_t(start);
91 large_size.QuadPart = size > 0 ? uint64_t(size) : uint64_t(-1);
92
94 overlapped.Offset = large_start.u.LowPart;
95 overlapped.OffsetHigh = large_start.u.HighPart;
96
97 switch(op)
98 {
99 case Lock_Operation::shared_lock:
100 return LockFileEx
101 (
102 file,
103 0,
104 0,
105 large_size.u.LowPart,
106 large_size.u.HighPart,
108 );
109 break;
110
111 case Lock_Operation::exclusive_lock:
112 return LockFileEx
113 (
114 file,
116 0,
117 large_size.u.LowPart,
118 large_size.u.HighPart,
120 );
121 break;
122
123 case Lock_Operation::unlock:
124 return UnlockFileEx
125 (
126 file,
127 0,
128 large_size.u.LowPart,
129 large_size.u.HighPart,
131 );
132 break;
133 }
134
135 return FALSE;
136 }
137
138 /////////////////////////////////////////////////////////////////////////////
139 void Windows_Handle::shared_lock(int64_t start, int64_t size)
140 /////////////////////////////////////////////////////////////////////////////
141 {
142 if (!lock(Lock_Operation::shared_lock, start, size))
143 throw_last_error("Read-locking", "file");
144 }
145
146 /////////////////////////////////////////////////////////////////////////////
147 void Windows_Handle::exclusive_lock(int64_t start, int64_t size)
148 /////////////////////////////////////////////////////////////////////////////
149 {
150 if (!lock(Lock_Operation::exclusive_lock, start, size))
151 throw_last_error("Write-locking", "file");
152 }
153
154 /////////////////////////////////////////////////////////////////////////////
155 void Windows_Handle::unlock(int64_t start, int64_t size) noexcept
156 /////////////////////////////////////////////////////////////////////////////
157 {
158 lock(Lock_Operation::unlock, start, size);
159 }
160
161 /////////////////////////////////////////////////////////////////////////////
162 size_t Windows_Handle::pread(char* buffer, size_t size, int64_t offset) const
163 /////////////////////////////////////////////////////////////////////////////
164 {
165 OVERLAPPED overlapped{};
166 overlapped.Pointer = PVOID(offset);
167
168 DWORD result;
169
170 if (ReadFile(file, buffer, size_to_dword(size), &result, &overlapped))
171 return size_t(result);
172 else
173 {
174 if (GetLastError() == ERROR_HANDLE_EOF)
175 return 0;
176 else
177 throw_last_error("Reading", "file");
178 }
179
180 return 0;
181 }
182
183 /////////////////////////////////////////////////////////////////////////////
185 /////////////////////////////////////////////////////////////////////////////
186 (
187 const char* buffer,
188 size_t size,
189 int64_t offset
190 )
191 {
192 size_t written = 0;
193
194 while (written < size)
195 {
196 OVERLAPPED overlapped{};
197 overlapped.Pointer = PVOID(offset + written);
198
199 DWORD actually_written;
200
201 if
202 (
203 !WriteFile
204 (
205 file,
206 buffer + written,
207 size_to_dword(size - written),
208 &actually_written,
209 &overlapped
210 )
211 )
212 {
213 throw_last_error("Writing", "file");
214 }
215
216 written += actually_written;
217 }
218 }
219
220 /////////////////////////////////////////////////////////////////////////////
222 /////////////////////////////////////////////////////////////////////////////
223 {
224 if (FlushFileBuffers(file) == 0)
225 throw_last_error("syncing", "file");
226 }
227
228 /////////////////////////////////////////////////////////////////////////////
229 Windows_Handle::Windows_Handle(const char *file_name, const Open_Mode mode):
230 /////////////////////////////////////////////////////////////////////////////
231 Buffered_File(mode),
232 file
233 (
234 CreateFileA
235 (
236 file_name,
237 desired_access[static_cast<size_t>(mode)],
238 share_mode[static_cast<size_t>(mode)],
239 NULL,
240 creation_disposition[static_cast<size_t>(mode)],
241 FILE_ATTRIBUTE_NORMAL,
242 NULL
243 )
244 )
245 {
246 if (file == INVALID_HANDLE_VALUE)
247 throw_last_error("Opening", file_name);
248 }
249
250 /////////////////////////////////////////////////////////////////////////////
251 Windows_File::Windows_File(const char *file_name, const Open_Mode mode):
252 /////////////////////////////////////////////////////////////////////////////
253 Windows_Handle(file_name, mode)
254 {
255 if (mode == Open_Mode::write_lock)
257 }
258
259 /////////////////////////////////////////////////////////////////////////////
261 /////////////////////////////////////////////////////////////////////////////
262 {
264
265 if (GetFileSizeEx(file, &result))
266 return int64_t(result.QuadPart);
267 else
268 throw_last_error("Getting size of", "file");
269
270 return -1;
271 }
272
273 /////////////////////////////////////////////////////////////////////////////
275 /////////////////////////////////////////////////////////////////////////////
276 {
278 CloseHandle(file);
279 }
280}
void destructor_flush() noexcept
Windows_File(const char *file_name, Open_Mode mode)
Windows_Handle(const char *file_name, Open_Mode mode)
void pwrite(const char *data, size_t size, int64_t offset) override
int64_t get_size() const override
size_t pread(char *data, size_t size, int64_t offset) const override
Open_Mode
Definition Open_Mode.h:8
@ write_lock
like write_existing_or_create_new, but waits instead of failing if already locked
Definition Blob.h:7