]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/port/win/port_win.cc
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / rocksdb / port / win / port_win.cc
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5 //
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9
10 #if !defined(OS_WIN) && !defined(WIN32) && !defined(_WIN32)
11 #error Windows Specific Code
12 #endif
13
14 #include "port/win/port_win.h"
15
16 #include <io.h>
17 #include "port/port_dirent.h"
18 #include "port/sys_time.h"
19
20 #include <cstdlib>
21 #include <stdio.h>
22 #include <assert.h>
23 #include <string.h>
24
25 #include <memory>
26 #include <exception>
27 #include <chrono>
28
29 #ifdef ROCKSDB_WINDOWS_UTF8_FILENAMES
30 // utf8 <-> utf16
31 #include <string>
32 #include <locale>
33 #include <codecvt>
34 #endif
35
36 #include "util/logging.h"
37
38 namespace rocksdb {
39
40 extern const bool kDefaultToAdaptiveMutex = false;
41
42 namespace port {
43
44 #ifdef ROCKSDB_WINDOWS_UTF8_FILENAMES
45 std::string utf16_to_utf8(const std::wstring& utf16) {
46 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> convert;
47 return convert.to_bytes(utf16);
48 }
49
50 std::wstring utf8_to_utf16(const std::string& utf8) {
51 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
52 return converter.from_bytes(utf8);
53 }
54 #endif
55
56 void gettimeofday(struct timeval* tv, struct timezone* /* tz */) {
57 using namespace std::chrono;
58
59 microseconds usNow(
60 duration_cast<microseconds>(system_clock::now().time_since_epoch()));
61
62 seconds secNow(duration_cast<seconds>(usNow));
63
64 tv->tv_sec = static_cast<long>(secNow.count());
65 tv->tv_usec = static_cast<long>(usNow.count() -
66 duration_cast<microseconds>(secNow).count());
67 }
68
69 Mutex::~Mutex() {}
70
71 CondVar::~CondVar() {}
72
73 void CondVar::Wait() {
74 // Caller must ensure that mutex is held prior to calling this method
75 std::unique_lock<std::mutex> lk(mu_->getLock(), std::adopt_lock);
76 #ifndef NDEBUG
77 mu_->locked_ = false;
78 #endif
79 cv_.wait(lk);
80 #ifndef NDEBUG
81 mu_->locked_ = true;
82 #endif
83 // Release ownership of the lock as we don't want it to be unlocked when
84 // it goes out of scope (as we adopted the lock and didn't lock it ourselves)
85 lk.release();
86 }
87
88 bool CondVar::TimedWait(uint64_t abs_time_us) {
89
90 using namespace std::chrono;
91
92 // MSVC++ library implements wait_until in terms of wait_for so
93 // we need to convert absolute wait into relative wait.
94 microseconds usAbsTime(abs_time_us);
95
96 microseconds usNow(
97 duration_cast<microseconds>(system_clock::now().time_since_epoch()));
98 microseconds relTimeUs =
99 (usAbsTime > usNow) ? (usAbsTime - usNow) : microseconds::zero();
100
101 // Caller must ensure that mutex is held prior to calling this method
102 std::unique_lock<std::mutex> lk(mu_->getLock(), std::adopt_lock);
103 #ifndef NDEBUG
104 mu_->locked_ = false;
105 #endif
106 std::cv_status cvStatus = cv_.wait_for(lk, relTimeUs);
107 #ifndef NDEBUG
108 mu_->locked_ = true;
109 #endif
110 // Release ownership of the lock as we don't want it to be unlocked when
111 // it goes out of scope (as we adopted the lock and didn't lock it ourselves)
112 lk.release();
113
114 if (cvStatus == std::cv_status::timeout) {
115 return true;
116 }
117
118 return false;
119 }
120
121 void CondVar::Signal() { cv_.notify_one(); }
122
123 void CondVar::SignalAll() { cv_.notify_all(); }
124
125 int PhysicalCoreID() { return GetCurrentProcessorNumber(); }
126
127 void InitOnce(OnceType* once, void (*initializer)()) {
128 std::call_once(once->flag_, initializer);
129 }
130
131 // Private structure, exposed only by pointer
132 struct DIR {
133 HANDLE handle_;
134 bool firstread_;
135 RX_WIN32_FIND_DATA data_;
136 dirent entry_;
137
138 DIR() : handle_(INVALID_HANDLE_VALUE),
139 firstread_(true) {}
140
141 DIR(const DIR&) = delete;
142 DIR& operator=(const DIR&) = delete;
143
144 ~DIR() {
145 if (INVALID_HANDLE_VALUE != handle_) {
146 ::FindClose(handle_);
147 }
148 }
149 };
150
151 DIR* opendir(const char* name) {
152 if (!name || *name == 0) {
153 errno = ENOENT;
154 return nullptr;
155 }
156
157 std::string pattern(name);
158 pattern.append("\\").append("*");
159
160 std::unique_ptr<DIR> dir(new DIR);
161
162 dir->handle_ = RX_FindFirstFileEx(RX_FN(pattern).c_str(),
163 FindExInfoBasic, // Do not want alternative name
164 &dir->data_,
165 FindExSearchNameMatch,
166 NULL, // lpSearchFilter
167 0);
168
169 if (dir->handle_ == INVALID_HANDLE_VALUE) {
170 return nullptr;
171 }
172
173 RX_FILESTRING x(dir->data_.cFileName, RX_FNLEN(dir->data_.cFileName));
174 strcpy_s(dir->entry_.d_name, sizeof(dir->entry_.d_name),
175 FN_TO_RX(x).c_str());
176
177 return dir.release();
178 }
179
180 struct dirent* readdir(DIR* dirp) {
181 if (!dirp || dirp->handle_ == INVALID_HANDLE_VALUE) {
182 errno = EBADF;
183 return nullptr;
184 }
185
186 if (dirp->firstread_) {
187 dirp->firstread_ = false;
188 return &dirp->entry_;
189 }
190
191 auto ret = RX_FindNextFile(dirp->handle_, &dirp->data_);
192
193 if (ret == 0) {
194 return nullptr;
195 }
196
197 RX_FILESTRING x(dirp->data_.cFileName, RX_FNLEN(dirp->data_.cFileName));
198 strcpy_s(dirp->entry_.d_name, sizeof(dirp->entry_.d_name),
199 FN_TO_RX(x).c_str());
200
201 return &dirp->entry_;
202 }
203
204 int closedir(DIR* dirp) {
205 delete dirp;
206 return 0;
207 }
208
209 int truncate(const char* path, int64_t length) {
210 if (path == nullptr) {
211 errno = EFAULT;
212 return -1;
213 }
214 return rocksdb::port::Truncate(path, length);
215 }
216
217 int Truncate(std::string path, int64_t len) {
218
219 if (len < 0) {
220 errno = EINVAL;
221 return -1;
222 }
223
224 HANDLE hFile =
225 RX_CreateFile(RX_FN(path).c_str(), GENERIC_READ | GENERIC_WRITE,
226 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
227 NULL, // Security attrs
228 OPEN_EXISTING, // Truncate existing file only
229 FILE_ATTRIBUTE_NORMAL, NULL);
230
231 if (INVALID_HANDLE_VALUE == hFile) {
232 auto lastError = GetLastError();
233 if (lastError == ERROR_FILE_NOT_FOUND) {
234 errno = ENOENT;
235 } else if (lastError == ERROR_ACCESS_DENIED) {
236 errno = EACCES;
237 } else {
238 errno = EIO;
239 }
240 return -1;
241 }
242
243 int result = 0;
244 FILE_END_OF_FILE_INFO end_of_file;
245 end_of_file.EndOfFile.QuadPart = len;
246
247 if (!SetFileInformationByHandle(hFile, FileEndOfFileInfo, &end_of_file,
248 sizeof(FILE_END_OF_FILE_INFO))) {
249 errno = EIO;
250 result = -1;
251 }
252
253 CloseHandle(hFile);
254 return result;
255 }
256
257 void Crash(const std::string& srcfile, int srcline) {
258 fprintf(stdout, "Crashing at %s:%d\n", srcfile.c_str(), srcline);
259 fflush(stdout);
260 abort();
261 }
262
263 int GetMaxOpenFiles() { return -1; }
264
265 } // namespace port
266 } // namespace rocksdb