]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/port/win/port_win.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / port / win / port_win.cc
CommitLineData
7c673cae 1// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
11fdf7f2
TL
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).
7c673cae
FG
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
20effc67 10#if defined(OS_WIN)
7c673cae
FG
11
12#include "port/win/port_win.h"
13
1e59de90 14#include <assert.h>
7c673cae 15#include <io.h>
1e59de90 16#include <rpc.h>
7c673cae 17#include <stdio.h>
7c673cae
FG
18#include <string.h>
19
7c673cae 20#include <chrono>
1e59de90
TL
21#include <cstdlib>
22#include <exception>
23#include <memory>
24
25#include "port/port_dirent.h"
26#include "port/sys_time.h"
7c673cae 27
494da23a
TL
28#ifdef ROCKSDB_WINDOWS_UTF8_FILENAMES
29// utf8 <-> utf16
494da23a 30#include <codecvt>
1e59de90
TL
31#include <locale>
32#include <string>
494da23a
TL
33#endif
34
f67539c2 35#include "logging/logging.h"
7c673cae 36
f67539c2 37namespace ROCKSDB_NAMESPACE {
494da23a
TL
38
39extern const bool kDefaultToAdaptiveMutex = false;
40
7c673cae
FG
41namespace port {
42
494da23a
TL
43#ifdef ROCKSDB_WINDOWS_UTF8_FILENAMES
44std::string utf16_to_utf8(const std::wstring& utf16) {
1e59de90 45 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
494da23a
TL
46 return convert.to_bytes(utf16);
47}
48
49std::wstring utf8_to_utf16(const std::string& utf8) {
50 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
51 return converter.from_bytes(utf8);
52}
53#endif
54
1e59de90
TL
55void GetTimeOfDay(TimeVal* tv, struct timezone* /* tz */) {
56 std::chrono::microseconds usNow(
57 std::chrono::duration_cast<std::chrono::microseconds>(
58 std::chrono::system_clock::now().time_since_epoch()));
7c673cae 59
1e59de90
TL
60 std::chrono::seconds secNow(
61 std::chrono::duration_cast<std::chrono::seconds>(usNow));
7c673cae
FG
62
63 tv->tv_sec = static_cast<long>(secNow.count());
1e59de90
TL
64 tv->tv_usec = static_cast<long>(
65 usNow.count() -
66 std::chrono::duration_cast<std::chrono::microseconds>(secNow).count());
7c673cae
FG
67}
68
69Mutex::~Mutex() {}
70
71CondVar::~CondVar() {}
72
73void 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
88bool CondVar::TimedWait(uint64_t abs_time_us) {
7c673cae
FG
89 // MSVC++ library implements wait_until in terms of wait_for so
90 // we need to convert absolute wait into relative wait.
1e59de90 91 std::chrono::microseconds usAbsTime(abs_time_us);
7c673cae 92
1e59de90
TL
93 std::chrono::microseconds usNow(
94 std::chrono::duration_cast<std::chrono::microseconds>(
95 std::chrono::system_clock::now().time_since_epoch()));
96 std::chrono::microseconds relTimeUs = (usAbsTime > usNow)
97 ? (usAbsTime - usNow)
98 : std::chrono::microseconds::zero();
7c673cae
FG
99
100 // Caller must ensure that mutex is held prior to calling this method
101 std::unique_lock<std::mutex> lk(mu_->getLock(), std::adopt_lock);
20effc67
TL
102
103 // Work around https://github.com/microsoft/STL/issues/369
104#if defined(_MSC_VER) && \
105 (!defined(_MSVC_STL_UPDATE) || _MSVC_STL_UPDATE < 202008L)
1e59de90 106 if (relTimeUs == std::chrono::microseconds::zero()) {
20effc67
TL
107 lk.unlock();
108 lk.lock();
109 }
110#endif
7c673cae
FG
111#ifndef NDEBUG
112 mu_->locked_ = false;
113#endif
114 std::cv_status cvStatus = cv_.wait_for(lk, relTimeUs);
115#ifndef NDEBUG
116 mu_->locked_ = true;
117#endif
118 // Release ownership of the lock as we don't want it to be unlocked when
119 // it goes out of scope (as we adopted the lock and didn't lock it ourselves)
120 lk.release();
121
122 if (cvStatus == std::cv_status::timeout) {
123 return true;
124 }
125
126 return false;
127}
128
129void CondVar::Signal() { cv_.notify_one(); }
130
131void CondVar::SignalAll() { cv_.notify_all(); }
132
133int PhysicalCoreID() { return GetCurrentProcessorNumber(); }
134
135void InitOnce(OnceType* once, void (*initializer)()) {
136 std::call_once(once->flag_, initializer);
137}
138
139// Private structure, exposed only by pointer
140struct DIR {
1e59de90
TL
141 HANDLE handle_;
142 bool firstread_;
494da23a 143 RX_WIN32_FIND_DATA data_;
7c673cae
FG
144 dirent entry_;
145
1e59de90 146 DIR() : handle_(INVALID_HANDLE_VALUE), firstread_(true) {}
7c673cae
FG
147
148 DIR(const DIR&) = delete;
149 DIR& operator=(const DIR&) = delete;
150
151 ~DIR() {
11fdf7f2
TL
152 if (INVALID_HANDLE_VALUE != handle_) {
153 ::FindClose(handle_);
7c673cae
FG
154 }
155 }
156};
157
158DIR* opendir(const char* name) {
159 if (!name || *name == 0) {
160 errno = ENOENT;
161 return nullptr;
162 }
163
164 std::string pattern(name);
165 pattern.append("\\").append("*");
166
167 std::unique_ptr<DIR> dir(new DIR);
168
20effc67
TL
169 dir->handle_ =
170 RX_FindFirstFileEx(RX_FN(pattern).c_str(),
171 FindExInfoBasic, // Do not want alternative name
172 &dir->data_, FindExSearchNameMatch,
173 NULL, // lpSearchFilter
174 0);
7c673cae 175
11fdf7f2 176 if (dir->handle_ == INVALID_HANDLE_VALUE) {
7c673cae
FG
177 return nullptr;
178 }
179
494da23a 180 RX_FILESTRING x(dir->data_.cFileName, RX_FNLEN(dir->data_.cFileName));
20effc67 181 strcpy_s(dir->entry_.d_name, sizeof(dir->entry_.d_name), FN_TO_RX(x).c_str());
7c673cae
FG
182
183 return dir.release();
184}
185
186struct dirent* readdir(DIR* dirp) {
11fdf7f2 187 if (!dirp || dirp->handle_ == INVALID_HANDLE_VALUE) {
7c673cae
FG
188 errno = EBADF;
189 return nullptr;
190 }
191
192 if (dirp->firstread_) {
193 dirp->firstread_ = false;
194 return &dirp->entry_;
195 }
196
494da23a 197 auto ret = RX_FindNextFile(dirp->handle_, &dirp->data_);
7c673cae 198
11fdf7f2 199 if (ret == 0) {
7c673cae
FG
200 return nullptr;
201 }
202
494da23a 203 RX_FILESTRING x(dirp->data_.cFileName, RX_FNLEN(dirp->data_.cFileName));
20effc67 204 strcpy_s(dirp->entry_.d_name, sizeof(dirp->entry_.d_name),
494da23a 205 FN_TO_RX(x).c_str());
7c673cae
FG
206
207 return &dirp->entry_;
208}
209
210int closedir(DIR* dirp) {
211 delete dirp;
212 return 0;
213}
214
494da23a 215int truncate(const char* path, int64_t length) {
7c673cae
FG
216 if (path == nullptr) {
217 errno = EFAULT;
218 return -1;
219 }
f67539c2 220 return ROCKSDB_NAMESPACE::port::Truncate(path, length);
494da23a
TL
221}
222
223int Truncate(std::string path, int64_t len) {
7c673cae
FG
224 if (len < 0) {
225 errno = EINVAL;
226 return -1;
227 }
228
229 HANDLE hFile =
494da23a 230 RX_CreateFile(RX_FN(path).c_str(), GENERIC_READ | GENERIC_WRITE,
1e59de90
TL
231 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
232 NULL, // Security attrs
233 OPEN_EXISTING, // Truncate existing file only
234 FILE_ATTRIBUTE_NORMAL, NULL);
7c673cae
FG
235
236 if (INVALID_HANDLE_VALUE == hFile) {
237 auto lastError = GetLastError();
238 if (lastError == ERROR_FILE_NOT_FOUND) {
239 errno = ENOENT;
240 } else if (lastError == ERROR_ACCESS_DENIED) {
241 errno = EACCES;
242 } else {
243 errno = EIO;
244 }
245 return -1;
246 }
247
248 int result = 0;
249 FILE_END_OF_FILE_INFO end_of_file;
250 end_of_file.EndOfFile.QuadPart = len;
251
252 if (!SetFileInformationByHandle(hFile, FileEndOfFileInfo, &end_of_file,
253 sizeof(FILE_END_OF_FILE_INFO))) {
254 errno = EIO;
255 result = -1;
256 }
257
258 CloseHandle(hFile);
259 return result;
260}
261
262void Crash(const std::string& srcfile, int srcline) {
263 fprintf(stdout, "Crashing at %s:%d\n", srcfile.c_str(), srcline);
264 fflush(stdout);
265 abort();
266}
267
268int GetMaxOpenFiles() { return -1; }
269
f67539c2
TL
270// Assume 4KB page size
271const size_t kPageSize = 4U * 1024U;
272
20effc67
TL
273void SetCpuPriority(ThreadId id, CpuPriority priority) {
274 // Not supported
275 (void)id;
276 (void)priority;
277}
278
1e59de90
TL
279int64_t GetProcessID() { return GetCurrentProcessId(); }
280
281bool GenerateRfcUuid(std::string* output) {
282 UUID uuid;
283 UuidCreateSequential(&uuid);
284
285 RPC_CSTR rpc_str;
286 auto status = UuidToStringA(&uuid, &rpc_str);
287 if (status != RPC_S_OK) {
288 return false;
289 }
290
291 // rpc_str is nul-terminated
292 *output = reinterpret_cast<char*>(rpc_str);
293
294 status = RpcStringFreeA(&rpc_str);
295 assert(status == RPC_S_OK);
296
297 return true;
298}
299
7c673cae 300} // namespace port
f67539c2 301} // namespace ROCKSDB_NAMESPACE
20effc67
TL
302
303#endif