env_win.cc 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437
  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. #if defined(OS_WIN)
  10. #include "port/win/env_win.h"
  11. #include <direct.h> // _rmdir, _mkdir, _getcwd
  12. #include <errno.h>
  13. #include <io.h> // _access
  14. #include <rpc.h> // for uuid generation
  15. #include <shlwapi.h>
  16. #include <sys/stat.h>
  17. #include <sys/types.h>
  18. #include <windows.h>
  19. #include <winioctl.h>
  20. #include <algorithm>
  21. #include <ctime>
  22. #include <thread>
  23. #include "monitoring/iostats_context_imp.h"
  24. #include "monitoring/thread_status_updater.h"
  25. #include "monitoring/thread_status_util.h"
  26. #include "port/lang.h"
  27. #include "port/port.h"
  28. #include "port/port_dirent.h"
  29. #include "port/win/io_win.h"
  30. #include "port/win/win_logger.h"
  31. #include "rocksdb/env.h"
  32. #include "rocksdb/slice.h"
  33. #include "strsafe.h"
  34. #include "util/string_util.h"
  35. // Undefine the functions windows might use (again)...
  36. #undef GetCurrentTime
  37. #undef DeleteFile
  38. #undef LoadLibrary
  39. namespace ROCKSDB_NAMESPACE {
  40. ThreadStatusUpdater* CreateThreadStatusUpdater() {
  41. return new ThreadStatusUpdater();
  42. }
  43. namespace {
  44. // Sector size used when physical sector size cannot be obtained from device.
  45. static const size_t kSectorSize = 512;
  46. // RAII helpers for HANDLEs
  47. const auto CloseHandleFunc = [](HANDLE h) { ::CloseHandle(h); };
  48. using UniqueCloseHandlePtr = std::unique_ptr<void, decltype(CloseHandleFunc)>;
  49. const auto FindCloseFunc = [](HANDLE h) { ::FindClose(h); };
  50. using UniqueFindClosePtr = std::unique_ptr<void, decltype(FindCloseFunc)>;
  51. void WinthreadCall(const char* label, std::error_code result) {
  52. if (0 != result.value()) {
  53. fprintf(stderr, "Winthread %s: %s\n", label,
  54. errnoStr(result.value()).c_str());
  55. abort();
  56. }
  57. }
  58. } // namespace
  59. namespace port {
  60. WinClock::WinClock()
  61. : perf_counter_frequency_(0),
  62. nano_seconds_per_period_(0),
  63. GetSystemTimePreciseAsFileTime_(NULL) {
  64. {
  65. LARGE_INTEGER qpf;
  66. BOOL ret __attribute__((__unused__));
  67. ret = QueryPerformanceFrequency(&qpf);
  68. assert(ret == TRUE);
  69. perf_counter_frequency_ = qpf.QuadPart;
  70. if (std::nano::den % perf_counter_frequency_ == 0) {
  71. nano_seconds_per_period_ = std::nano::den / perf_counter_frequency_;
  72. }
  73. }
  74. HMODULE module = GetModuleHandle("kernel32.dll");
  75. if (module != NULL) {
  76. GetSystemTimePreciseAsFileTime_ =
  77. (FnGetSystemTimePreciseAsFileTime)(void*)GetProcAddress(
  78. module, "GetSystemTimePreciseAsFileTime");
  79. }
  80. }
  81. void WinClock::SleepForMicroseconds(int micros) {
  82. std::this_thread::sleep_for(std::chrono::microseconds(micros));
  83. }
  84. std::string WinClock::TimeToString(uint64_t secondsSince1970) {
  85. std::string result;
  86. const time_t seconds = secondsSince1970;
  87. const int maxsize = 64;
  88. struct tm t;
  89. errno_t ret = localtime_s(&t, &seconds);
  90. if (ret) {
  91. result = std::to_string(seconds);
  92. } else {
  93. result.resize(maxsize);
  94. char* p = &result[0];
  95. int len =
  96. snprintf(p, maxsize, "%04d/%02d/%02d-%02d:%02d:%02d ", t.tm_year + 1900,
  97. t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
  98. assert(len > 0);
  99. result.resize(len);
  100. }
  101. return result;
  102. }
  103. uint64_t WinClock::NowMicros() {
  104. if (GetSystemTimePreciseAsFileTime_ != NULL) {
  105. // all std::chrono clocks on windows proved to return
  106. // values that may repeat that is not good enough for some uses.
  107. const int64_t c_UnixEpochStartTicks = 116444736000000000LL;
  108. const int64_t c_FtToMicroSec = 10;
  109. // This interface needs to return system time and not
  110. // just any microseconds because it is often used as an argument
  111. // to TimedWait() on condition variable
  112. FILETIME ftSystemTime;
  113. GetSystemTimePreciseAsFileTime_(&ftSystemTime);
  114. LARGE_INTEGER li;
  115. li.LowPart = ftSystemTime.dwLowDateTime;
  116. li.HighPart = ftSystemTime.dwHighDateTime;
  117. // Subtract unix epoch start
  118. li.QuadPart -= c_UnixEpochStartTicks;
  119. // Convert to microsecs
  120. li.QuadPart /= c_FtToMicroSec;
  121. return li.QuadPart;
  122. }
  123. return std::chrono::duration_cast<std::chrono::microseconds>(
  124. std::chrono::system_clock::now().time_since_epoch())
  125. .count();
  126. }
  127. uint64_t WinClock::NowNanos() {
  128. if (nano_seconds_per_period_ != 0) {
  129. // all std::chrono clocks on windows have the same resolution that is only
  130. // good enough for microseconds but not nanoseconds
  131. // On Windows 8 and Windows 2012 Server
  132. // GetSystemTimePreciseAsFileTime(&current_time) can be used
  133. LARGE_INTEGER li;
  134. QueryPerformanceCounter(&li);
  135. // Convert performance counter to nanoseconds by precomputed ratio.
  136. // Directly multiply nano::den with li.QuadPart causes overflow.
  137. // Only do this when nano::den is divisible by perf_counter_frequency_,
  138. // which most likely is the case in reality. If it's not, fall back to
  139. // high_resolution_clock, which may be less precise under old compilers.
  140. li.QuadPart *= nano_seconds_per_period_;
  141. return li.QuadPart;
  142. }
  143. return std::chrono::duration_cast<std::chrono::nanoseconds>(
  144. std::chrono::high_resolution_clock::now().time_since_epoch())
  145. .count();
  146. }
  147. Status WinClock::GetCurrentTime(int64_t* unix_time) {
  148. time_t time = std::time(nullptr);
  149. if (time == (time_t)(-1)) {
  150. return Status::NotSupported("Failed to get time");
  151. }
  152. *unix_time = time;
  153. return Status::OK();
  154. }
  155. WinFileSystem::WinFileSystem(const std::shared_ptr<SystemClock>& clock)
  156. : clock_(clock), page_size_(4 * 1024), allocation_granularity_(page_size_) {
  157. SYSTEM_INFO sinfo;
  158. GetSystemInfo(&sinfo);
  159. page_size_ = sinfo.dwPageSize;
  160. allocation_granularity_ = sinfo.dwAllocationGranularity;
  161. }
  162. const std::shared_ptr<WinFileSystem>& WinFileSystem::Default() {
  163. STATIC_AVOID_DESTRUCTION(std::shared_ptr<WinFileSystem>, fs)
  164. (std::make_shared<WinFileSystem>(WinClock::Default()));
  165. return fs;
  166. }
  167. WinEnvIO::WinEnvIO(Env* hosted_env) : hosted_env_(hosted_env) {}
  168. WinEnvIO::~WinEnvIO() {}
  169. IOStatus WinFileSystem::DeleteFile(const std::string& fname,
  170. const IOOptions& /*options*/,
  171. IODebugContext* /*dbg*/) {
  172. IOStatus result;
  173. BOOL ret = RX_DeleteFile(RX_FN(fname).c_str());
  174. if (!ret) {
  175. auto lastError = GetLastError();
  176. result = IOErrorFromWindowsError("Failed to delete: " + fname, lastError);
  177. }
  178. return result;
  179. }
  180. IOStatus WinFileSystem::Truncate(const std::string& fname, size_t size,
  181. const IOOptions& /*options*/,
  182. IODebugContext* /*dbg*/) {
  183. IOStatus s;
  184. int result = ROCKSDB_NAMESPACE::port::Truncate(fname, size);
  185. if (result != 0) {
  186. s = IOError("Failed to truncate: " + fname, errno);
  187. }
  188. return s;
  189. }
  190. IOStatus WinFileSystem::NewSequentialFile(
  191. const std::string& fname, const FileOptions& options,
  192. std::unique_ptr<FSSequentialFile>* result, IODebugContext* /*dbg*/) {
  193. IOStatus s;
  194. result->reset();
  195. // Corruption test needs to rename and delete files of these kind
  196. // while they are still open with another handle. For that reason we
  197. // allow share_write and delete(allows rename).
  198. HANDLE hFile = INVALID_HANDLE_VALUE;
  199. DWORD fileFlags = FILE_ATTRIBUTE_READONLY;
  200. if (options.use_direct_reads && !options.use_mmap_reads) {
  201. fileFlags |= FILE_FLAG_NO_BUFFERING;
  202. }
  203. {
  204. IOSTATS_TIMER_GUARD(open_nanos);
  205. hFile = RX_CreateFile(
  206. RX_FN(fname).c_str(), GENERIC_READ,
  207. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
  208. OPEN_EXISTING, // Original fopen mode is "rb"
  209. fileFlags, NULL);
  210. }
  211. if (INVALID_HANDLE_VALUE == hFile) {
  212. auto lastError = GetLastError();
  213. s = IOErrorFromWindowsError("Failed to open NewSequentialFile" + fname,
  214. lastError);
  215. } else {
  216. result->reset(new WinSequentialFile(fname, hFile, options));
  217. }
  218. return s;
  219. }
  220. IOStatus WinFileSystem::NewRandomAccessFile(
  221. const std::string& fname, const FileOptions& options,
  222. std::unique_ptr<FSRandomAccessFile>* result, IODebugContext* dbg) {
  223. result->reset();
  224. IOStatus s;
  225. // Open the file for read-only random access
  226. // Random access is to disable read-ahead as the system reads too much data
  227. DWORD fileFlags = FILE_ATTRIBUTE_READONLY;
  228. if (options.use_direct_reads && !options.use_mmap_reads) {
  229. fileFlags |= FILE_FLAG_NO_BUFFERING;
  230. } else {
  231. fileFlags |= FILE_FLAG_RANDOM_ACCESS;
  232. }
  233. /// Shared access is necessary for corruption test to pass
  234. // almost all tests would work with a possible exception of fault_injection
  235. HANDLE hFile = 0;
  236. {
  237. IOSTATS_TIMER_GUARD(open_nanos);
  238. hFile =
  239. RX_CreateFile(RX_FN(fname).c_str(), GENERIC_READ,
  240. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  241. NULL, OPEN_EXISTING, fileFlags, NULL);
  242. }
  243. if (INVALID_HANDLE_VALUE == hFile) {
  244. auto lastError = GetLastError();
  245. return IOErrorFromWindowsError(
  246. "NewRandomAccessFile failed to Create/Open: " + fname, lastError);
  247. }
  248. UniqueCloseHandlePtr fileGuard(hFile, CloseHandleFunc);
  249. // CAUTION! This will map the entire file into the process address space.
  250. // Not recommended for 32-bit platforms.
  251. if (options.use_mmap_reads) {
  252. uint64_t fileSize;
  253. s = GetFileSize(fname, IOOptions(), &fileSize, dbg);
  254. if (s.ok()) {
  255. // Will not map empty files
  256. if (fileSize == 0) {
  257. return IOError("NewRandomAccessFile failed to map empty file: " + fname,
  258. EINVAL);
  259. }
  260. HANDLE hMap = RX_CreateFileMapping(hFile, NULL, PAGE_READONLY,
  261. 0, // At its present length
  262. 0,
  263. NULL); // Mapping name
  264. if (!hMap) {
  265. auto lastError = GetLastError();
  266. return IOErrorFromWindowsError(
  267. "Failed to create file mapping for NewRandomAccessFile: " + fname,
  268. lastError);
  269. }
  270. UniqueCloseHandlePtr mapGuard(hMap, CloseHandleFunc);
  271. const void* mapped_region =
  272. MapViewOfFileEx(hMap, FILE_MAP_READ,
  273. 0, // High DWORD of access start
  274. 0, // Low DWORD
  275. static_cast<SIZE_T>(fileSize),
  276. NULL); // Let the OS choose the mapping
  277. if (!mapped_region) {
  278. auto lastError = GetLastError();
  279. return IOErrorFromWindowsError(
  280. "Failed to MapViewOfFile for NewRandomAccessFile: " + fname,
  281. lastError);
  282. }
  283. result->reset(new WinMmapReadableFile(fname, hFile, hMap, mapped_region,
  284. static_cast<size_t>(fileSize)));
  285. mapGuard.release();
  286. fileGuard.release();
  287. }
  288. } else {
  289. result->reset(new WinRandomAccessFile(fname, hFile, page_size_, options));
  290. fileGuard.release();
  291. }
  292. return s;
  293. }
  294. IOStatus WinFileSystem::OpenWritableFile(
  295. const std::string& fname, const FileOptions& options,
  296. std::unique_ptr<FSWritableFile>* result, bool reopen) {
  297. const size_t c_BufferCapacity = 64 * 1024;
  298. EnvOptions local_options(options);
  299. result->reset();
  300. IOStatus s;
  301. DWORD fileFlags = FILE_ATTRIBUTE_NORMAL;
  302. if (local_options.use_direct_writes && !local_options.use_mmap_writes) {
  303. fileFlags = FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
  304. }
  305. // Desired access. We are want to write only here but if we want to memory
  306. // map
  307. // the file then there is no write only mode so we have to create it
  308. // Read/Write
  309. // However, MapViewOfFile specifies only Write only
  310. DWORD desired_access = GENERIC_WRITE;
  311. DWORD shared_mode = FILE_SHARE_READ;
  312. if (local_options.use_mmap_writes) {
  313. desired_access |= GENERIC_READ;
  314. } else {
  315. // Adding this solely for tests to pass (fault_injection_test,
  316. // wal_manager_test).
  317. shared_mode |= (FILE_SHARE_WRITE | FILE_SHARE_DELETE);
  318. }
  319. // This will always truncate the file
  320. DWORD creation_disposition = CREATE_ALWAYS;
  321. if (reopen) {
  322. creation_disposition = OPEN_ALWAYS;
  323. }
  324. HANDLE hFile = 0;
  325. {
  326. IOSTATS_TIMER_GUARD(open_nanos);
  327. hFile = RX_CreateFile(
  328. RX_FN(fname).c_str(),
  329. desired_access, // Access desired
  330. shared_mode,
  331. NULL, // Security attributes
  332. // Posix env says (reopen) ? (O_CREATE | O_APPEND) : O_CREAT | O_TRUNC
  333. creation_disposition,
  334. fileFlags, // Flags
  335. NULL); // Template File
  336. }
  337. if (INVALID_HANDLE_VALUE == hFile) {
  338. auto lastError = GetLastError();
  339. return IOErrorFromWindowsError(
  340. "Failed to create a NewWritableFile: " + fname, lastError);
  341. }
  342. // We will start writing at the end, appending
  343. if (reopen) {
  344. LARGE_INTEGER zero_move;
  345. zero_move.QuadPart = 0;
  346. BOOL ret = SetFilePointerEx(hFile, zero_move, NULL, FILE_END);
  347. if (!ret) {
  348. auto lastError = GetLastError();
  349. return IOErrorFromWindowsError(
  350. "Failed to create a ReopenWritableFile move to the end: " + fname,
  351. lastError);
  352. }
  353. }
  354. if (options.use_mmap_writes) {
  355. // We usually do not use mmmapping on SSD and thus we pass memory
  356. // page_size
  357. result->reset(new WinMmapFile(fname, hFile, page_size_,
  358. allocation_granularity_, local_options));
  359. } else {
  360. // Here we want the buffer allocation to be aligned by the SSD page size
  361. // and to be a multiple of it
  362. result->reset(new WinWritableFile(fname, hFile, GetPageSize(),
  363. c_BufferCapacity, local_options));
  364. }
  365. return s;
  366. }
  367. IOStatus WinFileSystem::NewWritableFile(const std::string& fname,
  368. const FileOptions& options,
  369. std::unique_ptr<FSWritableFile>* result,
  370. IODebugContext* /*dbg*/) {
  371. return OpenWritableFile(fname, options, result, false);
  372. }
  373. IOStatus WinFileSystem::ReopenWritableFile(
  374. const std::string& fname, const FileOptions& options,
  375. std::unique_ptr<FSWritableFile>* result, IODebugContext* /*dbg*/) {
  376. return OpenWritableFile(fname, options, result, true);
  377. }
  378. IOStatus WinFileSystem::NewRandomRWFile(const std::string& fname,
  379. const FileOptions& options,
  380. std::unique_ptr<FSRandomRWFile>* result,
  381. IODebugContext* /*dbg*/) {
  382. IOStatus s;
  383. // Open the file for read-only random access
  384. // Random access is to disable read-ahead as the system reads too much data
  385. DWORD desired_access = GENERIC_READ | GENERIC_WRITE;
  386. DWORD shared_mode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
  387. DWORD creation_disposition = OPEN_EXISTING; // Fail if file does not exist
  388. DWORD file_flags = FILE_FLAG_RANDOM_ACCESS;
  389. if (options.use_direct_reads && options.use_direct_writes) {
  390. file_flags |= FILE_FLAG_NO_BUFFERING;
  391. }
  392. /// Shared access is necessary for corruption test to pass
  393. // almost all tests would work with a possible exception of fault_injection
  394. HANDLE hFile = 0;
  395. {
  396. IOSTATS_TIMER_GUARD(open_nanos);
  397. hFile = RX_CreateFile(RX_FN(fname).c_str(), desired_access, shared_mode,
  398. NULL, // Security attributes
  399. creation_disposition, file_flags, NULL);
  400. }
  401. if (INVALID_HANDLE_VALUE == hFile) {
  402. auto lastError = GetLastError();
  403. return IOErrorFromWindowsError(
  404. "NewRandomRWFile failed to Create/Open: " + fname, lastError);
  405. }
  406. UniqueCloseHandlePtr fileGuard(hFile, CloseHandleFunc);
  407. result->reset(new WinRandomRWFile(fname, hFile, GetPageSize(), options));
  408. fileGuard.release();
  409. return s;
  410. }
  411. IOStatus WinFileSystem::NewMemoryMappedFileBuffer(
  412. const std::string& fname, std::unique_ptr<MemoryMappedFileBuffer>* result) {
  413. IOStatus s;
  414. result->reset();
  415. DWORD fileFlags = FILE_ATTRIBUTE_READONLY;
  416. HANDLE hFile = INVALID_HANDLE_VALUE;
  417. {
  418. IOSTATS_TIMER_GUARD(open_nanos);
  419. hFile = RX_CreateFile(
  420. RX_FN(fname).c_str(), GENERIC_READ | GENERIC_WRITE,
  421. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
  422. OPEN_EXISTING, // Open only if it exists
  423. fileFlags, NULL);
  424. }
  425. if (INVALID_HANDLE_VALUE == hFile) {
  426. auto lastError = GetLastError();
  427. s = IOErrorFromWindowsError(
  428. "Failed to open NewMemoryMappedFileBuffer: " + fname, lastError);
  429. return s;
  430. }
  431. UniqueCloseHandlePtr fileGuard(hFile, CloseHandleFunc);
  432. uint64_t fileSize = 0;
  433. s = GetFileSize(fname, IOOptions(), &fileSize, nullptr);
  434. if (!s.ok()) {
  435. return s;
  436. }
  437. // Will not map empty files
  438. if (fileSize == 0) {
  439. return IOStatus::NotSupported(
  440. "NewMemoryMappedFileBuffer can not map zero length files: " + fname);
  441. }
  442. // size_t is 32-bit with 32-bit builds
  443. if (fileSize > std::numeric_limits<size_t>::max()) {
  444. return IOStatus::NotSupported(
  445. "The specified file size does not fit into 32-bit memory addressing: " +
  446. fname);
  447. }
  448. HANDLE hMap = RX_CreateFileMapping(hFile, NULL, PAGE_READWRITE,
  449. 0, // Whole file at its present length
  450. 0,
  451. NULL); // Mapping name
  452. if (!hMap) {
  453. auto lastError = GetLastError();
  454. return IOErrorFromWindowsError(
  455. "Failed to create file mapping for: " + fname, lastError);
  456. }
  457. UniqueCloseHandlePtr mapGuard(hMap, CloseHandleFunc);
  458. void* base = MapViewOfFileEx(hMap, FILE_MAP_WRITE,
  459. 0, // High DWORD of access start
  460. 0, // Low DWORD
  461. static_cast<SIZE_T>(fileSize),
  462. NULL); // Let the OS choose the mapping
  463. if (!base) {
  464. auto lastError = GetLastError();
  465. return IOErrorFromWindowsError(
  466. "Failed to MapViewOfFile for NewMemoryMappedFileBuffer: " + fname,
  467. lastError);
  468. }
  469. result->reset(new WinMemoryMappedBuffer(hFile, hMap, base,
  470. static_cast<size_t>(fileSize)));
  471. mapGuard.release();
  472. fileGuard.release();
  473. return s;
  474. }
  475. IOStatus WinFileSystem::NewDirectory(const std::string& name,
  476. const IOOptions& /*options*/,
  477. std::unique_ptr<FSDirectory>* result,
  478. IODebugContext* /*dbg*/) {
  479. IOStatus s;
  480. // Must be nullptr on failure
  481. result->reset();
  482. if (!DirExists(name)) {
  483. s = IOErrorFromWindowsError("open folder: " + name, ERROR_DIRECTORY);
  484. return s;
  485. }
  486. HANDLE handle = INVALID_HANDLE_VALUE;
  487. // 0 - for access means read metadata
  488. {
  489. IOSTATS_TIMER_GUARD(open_nanos);
  490. handle = RX_CreateFile(
  491. RX_FN(name).c_str(), 0,
  492. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  493. OPEN_EXISTING,
  494. FILE_FLAG_BACKUP_SEMANTICS, // make opening folders possible
  495. NULL);
  496. }
  497. if (INVALID_HANDLE_VALUE == handle) {
  498. auto lastError = GetLastError();
  499. s = IOErrorFromWindowsError("open folder: " + name, lastError);
  500. return s;
  501. }
  502. result->reset(new WinDirectory(name, handle));
  503. return s;
  504. }
  505. IOStatus WinFileSystem::FileExists(const std::string& fname,
  506. const IOOptions& /*opts*/,
  507. IODebugContext* /*dbg*/) {
  508. IOStatus s;
  509. // TODO: This does not follow symbolic links at this point
  510. // which is consistent with _access() impl on windows
  511. // but can be added
  512. WIN32_FILE_ATTRIBUTE_DATA attrs;
  513. if (FALSE == RX_GetFileAttributesEx(RX_FN(fname).c_str(),
  514. GetFileExInfoStandard, &attrs)) {
  515. auto lastError = GetLastError();
  516. switch (lastError) {
  517. case ERROR_ACCESS_DENIED:
  518. case ERROR_NOT_FOUND:
  519. case ERROR_FILE_NOT_FOUND:
  520. case ERROR_PATH_NOT_FOUND:
  521. s = IOStatus::NotFound();
  522. break;
  523. default:
  524. s = IOErrorFromWindowsError("Unexpected error for: " + fname,
  525. lastError);
  526. break;
  527. }
  528. }
  529. return s;
  530. }
  531. IOStatus WinFileSystem::GetChildren(const std::string& dir,
  532. const IOOptions& /*opts*/,
  533. std::vector<std::string>* result,
  534. IODebugContext* /*dbg*/) {
  535. IOStatus status;
  536. result->clear();
  537. RX_WIN32_FIND_DATA data;
  538. memset(&data, 0, sizeof(data));
  539. std::string pattern(dir);
  540. pattern.append("\\").append("*");
  541. HANDLE handle =
  542. RX_FindFirstFileEx(RX_FN(pattern).c_str(),
  543. // Do not want alternative name
  544. FindExInfoBasic, &data, FindExSearchNameMatch,
  545. NULL, // lpSearchFilter
  546. 0);
  547. if (handle == INVALID_HANDLE_VALUE) {
  548. auto lastError = GetLastError();
  549. switch (lastError) {
  550. case ERROR_NOT_FOUND:
  551. case ERROR_ACCESS_DENIED:
  552. case ERROR_FILE_NOT_FOUND:
  553. case ERROR_PATH_NOT_FOUND:
  554. status = IOStatus::NotFound();
  555. break;
  556. default:
  557. status = IOErrorFromWindowsError("Failed to GetChhildren for: " + dir,
  558. lastError);
  559. }
  560. return status;
  561. }
  562. UniqueFindClosePtr fc(handle, FindCloseFunc);
  563. // For safety
  564. data.cFileName[MAX_PATH - 1] = 0;
  565. while (true) {
  566. // filter out '.' and '..' directory entries
  567. // which appear only on some platforms
  568. const bool ignore =
  569. ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) &&
  570. (RX_FNCMP(data.cFileName, ".") == 0 ||
  571. RX_FNCMP(data.cFileName, "..") == 0);
  572. if (!ignore) {
  573. auto x = RX_FILESTRING(data.cFileName, RX_FNLEN(data.cFileName));
  574. result->push_back(FN_TO_RX(x));
  575. }
  576. BOOL ret = -RX_FindNextFile(handle, &data);
  577. // If the function fails the return value is zero
  578. // and non-zero otherwise. Not TRUE or FALSE.
  579. if (ret == FALSE) {
  580. // Posix does not care why we stopped
  581. break;
  582. }
  583. data.cFileName[MAX_PATH - 1] = 0;
  584. }
  585. return status;
  586. }
  587. IOStatus WinFileSystem::CreateDir(const std::string& name,
  588. const IOOptions& /*opts*/,
  589. IODebugContext* /*dbg*/) {
  590. IOStatus result;
  591. BOOL ret = RX_CreateDirectory(RX_FN(name).c_str(), NULL);
  592. if (!ret) {
  593. auto lastError = GetLastError();
  594. result = IOErrorFromWindowsError("Failed to create a directory: " + name,
  595. lastError);
  596. }
  597. return result;
  598. }
  599. IOStatus WinFileSystem::CreateDirIfMissing(const std::string& name,
  600. const IOOptions& /*opts*/,
  601. IODebugContext* /*dbg*/) {
  602. IOStatus result;
  603. if (DirExists(name)) {
  604. return result;
  605. }
  606. BOOL ret = RX_CreateDirectory(RX_FN(name).c_str(), NULL);
  607. if (!ret) {
  608. auto lastError = GetLastError();
  609. if (lastError != ERROR_ALREADY_EXISTS) {
  610. result = IOErrorFromWindowsError("Failed to create a directory: " + name,
  611. lastError);
  612. } else {
  613. result = IOStatus::IOError(name + ": exists but is not a directory");
  614. }
  615. }
  616. return result;
  617. }
  618. IOStatus WinFileSystem::DeleteDir(const std::string& name,
  619. const IOOptions& /*options*/,
  620. IODebugContext* /*dbg*/) {
  621. IOStatus result;
  622. BOOL ret = RX_RemoveDirectory(RX_FN(name).c_str());
  623. if (!ret) {
  624. auto lastError = GetLastError();
  625. result =
  626. IOErrorFromWindowsError("Failed to remove dir: " + name, lastError);
  627. }
  628. return result;
  629. }
  630. IOStatus WinFileSystem::GetFileSize(const std::string& fname,
  631. const IOOptions& /*opts*/, uint64_t* size,
  632. IODebugContext* /*dbg*/) {
  633. IOStatus s;
  634. WIN32_FILE_ATTRIBUTE_DATA attrs;
  635. if (RX_GetFileAttributesEx(RX_FN(fname).c_str(), GetFileExInfoStandard,
  636. &attrs)) {
  637. ULARGE_INTEGER file_size;
  638. file_size.HighPart = attrs.nFileSizeHigh;
  639. file_size.LowPart = attrs.nFileSizeLow;
  640. *size = file_size.QuadPart;
  641. } else {
  642. auto lastError = GetLastError();
  643. s = IOErrorFromWindowsError("Can not get size for: " + fname, lastError);
  644. }
  645. return s;
  646. }
  647. uint64_t WinFileSystem::FileTimeToUnixTime(const FILETIME& ftTime) {
  648. const uint64_t c_FileTimePerSecond = 10000000U;
  649. // UNIX epoch starts on 1970-01-01T00:00:00Z
  650. // Windows FILETIME starts on 1601-01-01T00:00:00Z
  651. // Therefore, we need to subtract the below number of seconds from
  652. // the seconds that we obtain from FILETIME with an obvious loss of
  653. // precision
  654. const uint64_t c_SecondBeforeUnixEpoch = 11644473600U;
  655. ULARGE_INTEGER li;
  656. li.HighPart = ftTime.dwHighDateTime;
  657. li.LowPart = ftTime.dwLowDateTime;
  658. uint64_t result =
  659. (li.QuadPart / c_FileTimePerSecond) - c_SecondBeforeUnixEpoch;
  660. return result;
  661. }
  662. IOStatus WinFileSystem::GetFileModificationTime(const std::string& fname,
  663. const IOOptions& /*opts*/,
  664. uint64_t* file_mtime,
  665. IODebugContext* /*dbg*/) {
  666. IOStatus s;
  667. WIN32_FILE_ATTRIBUTE_DATA attrs;
  668. if (RX_GetFileAttributesEx(RX_FN(fname).c_str(), GetFileExInfoStandard,
  669. &attrs)) {
  670. *file_mtime = FileTimeToUnixTime(attrs.ftLastWriteTime);
  671. } else {
  672. auto lastError = GetLastError();
  673. s = IOErrorFromWindowsError(
  674. "Can not get file modification time for: " + fname, lastError);
  675. *file_mtime = 0;
  676. }
  677. return s;
  678. }
  679. IOStatus WinFileSystem::RenameFile(const std::string& src,
  680. const std::string& target,
  681. const IOOptions& /*opts*/,
  682. IODebugContext* /*dbg*/) {
  683. IOStatus result;
  684. // rename() is not capable of replacing the existing file as on Linux
  685. // so use OS API directly
  686. if (!RX_MoveFileEx(RX_FN(src).c_str(), RX_FN(target).c_str(),
  687. MOVEFILE_REPLACE_EXISTING)) {
  688. DWORD lastError = GetLastError();
  689. std::string text("Failed to rename: ");
  690. text.append(src).append(" to: ").append(target);
  691. result = IOErrorFromWindowsError(text, lastError);
  692. }
  693. return result;
  694. }
  695. IOStatus WinFileSystem::LinkFile(const std::string& src,
  696. const std::string& target,
  697. const IOOptions& /*opts*/,
  698. IODebugContext* /*dbg*/) {
  699. IOStatus result;
  700. if (!RX_CreateHardLink(RX_FN(target).c_str(), RX_FN(src).c_str(), NULL)) {
  701. DWORD lastError = GetLastError();
  702. if (lastError == ERROR_NOT_SAME_DEVICE) {
  703. return IOStatus::NotSupported("No cross FS links allowed");
  704. }
  705. std::string text("Failed to link: ");
  706. text.append(src).append(" to: ").append(target);
  707. result = IOErrorFromWindowsError(text, lastError);
  708. }
  709. return result;
  710. }
  711. IOStatus WinFileSystem::NumFileLinks(const std::string& fname,
  712. const IOOptions& /*opts*/, uint64_t* count,
  713. IODebugContext* /*dbg*/) {
  714. IOStatus s;
  715. HANDLE handle =
  716. RX_CreateFile(RX_FN(fname).c_str(), 0,
  717. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  718. NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
  719. if (INVALID_HANDLE_VALUE == handle) {
  720. auto lastError = GetLastError();
  721. s = IOErrorFromWindowsError("NumFileLinks: " + fname, lastError);
  722. return s;
  723. }
  724. UniqueCloseHandlePtr handle_guard(handle, CloseHandleFunc);
  725. FILE_STANDARD_INFO standard_info;
  726. if (0 != GetFileInformationByHandleEx(handle, FileStandardInfo,
  727. &standard_info,
  728. sizeof(standard_info))) {
  729. *count = standard_info.NumberOfLinks;
  730. } else {
  731. auto lastError = GetLastError();
  732. s = IOErrorFromWindowsError("GetFileInformationByHandleEx: " + fname,
  733. lastError);
  734. }
  735. return s;
  736. }
  737. IOStatus WinFileSystem::AreFilesSame(const std::string& first,
  738. const std::string& second,
  739. const IOOptions& /*opts*/, bool* res,
  740. IODebugContext* /*dbg*/) {
  741. // For MinGW builds
  742. #if (_WIN32_WINNT == _WIN32_WINNT_VISTA)
  743. IOStatus s = IOStatus::NotSupported();
  744. #else
  745. assert(res != nullptr);
  746. IOStatus s;
  747. if (res == nullptr) {
  748. s = IOStatus::InvalidArgument("res");
  749. return s;
  750. }
  751. // 0 - for access means read metadata
  752. HANDLE file_1 = RX_CreateFile(
  753. RX_FN(first).c_str(), 0,
  754. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  755. OPEN_EXISTING,
  756. FILE_FLAG_BACKUP_SEMANTICS, // make opening folders possible
  757. NULL);
  758. if (INVALID_HANDLE_VALUE == file_1) {
  759. auto lastError = GetLastError();
  760. s = IOErrorFromWindowsError("open file: " + first, lastError);
  761. return s;
  762. }
  763. UniqueCloseHandlePtr g_1(file_1, CloseHandleFunc);
  764. HANDLE file_2 = RX_CreateFile(
  765. RX_FN(second).c_str(), 0,
  766. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  767. OPEN_EXISTING,
  768. FILE_FLAG_BACKUP_SEMANTICS, // make opening folders possible
  769. NULL);
  770. if (INVALID_HANDLE_VALUE == file_2) {
  771. auto lastError = GetLastError();
  772. s = IOErrorFromWindowsError("open file: " + second, lastError);
  773. return s;
  774. }
  775. UniqueCloseHandlePtr g_2(file_2, CloseHandleFunc);
  776. FILE_ID_INFO FileInfo_1;
  777. BOOL result = GetFileInformationByHandleEx(file_1, FileIdInfo, &FileInfo_1,
  778. sizeof(FileInfo_1));
  779. if (!result) {
  780. auto lastError = GetLastError();
  781. s = IOErrorFromWindowsError("stat file: " + first, lastError);
  782. return s;
  783. }
  784. FILE_ID_INFO FileInfo_2;
  785. result = GetFileInformationByHandleEx(file_2, FileIdInfo, &FileInfo_2,
  786. sizeof(FileInfo_2));
  787. if (!result) {
  788. auto lastError = GetLastError();
  789. s = IOErrorFromWindowsError("stat file: " + second, lastError);
  790. return s;
  791. }
  792. if (FileInfo_1.VolumeSerialNumber == FileInfo_2.VolumeSerialNumber) {
  793. *res =
  794. (0 == memcmp(FileInfo_1.FileId.Identifier, FileInfo_2.FileId.Identifier,
  795. sizeof(FileInfo_1.FileId.Identifier)));
  796. } else {
  797. *res = false;
  798. }
  799. #endif
  800. return s;
  801. }
  802. IOStatus WinFileSystem::LockFile(const std::string& lockFname,
  803. const IOOptions& /*opts*/, FileLock** lock,
  804. IODebugContext* /*dbg*/) {
  805. assert(lock != nullptr);
  806. *lock = NULL;
  807. IOStatus result;
  808. // No-sharing, this is a LOCK file
  809. const DWORD ExclusiveAccessON = 0;
  810. // Obtain exclusive access to the LOCK file
  811. // Previously, instead of NORMAL attr we set DELETE on close and that worked
  812. // well except with fault_injection test that insists on deleting it.
  813. HANDLE hFile = 0;
  814. {
  815. IOSTATS_TIMER_GUARD(open_nanos);
  816. hFile = RX_CreateFile(RX_FN(lockFname).c_str(),
  817. (GENERIC_READ | GENERIC_WRITE), ExclusiveAccessON,
  818. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  819. }
  820. if (INVALID_HANDLE_VALUE == hFile) {
  821. auto lastError = GetLastError();
  822. result = IOErrorFromWindowsError("Failed to create lock file: " + lockFname,
  823. lastError);
  824. } else {
  825. *lock = new WinFileLock(hFile);
  826. }
  827. return result;
  828. }
  829. IOStatus WinFileSystem::UnlockFile(FileLock* lock, const IOOptions& /*opts*/,
  830. IODebugContext* /*dbg*/) {
  831. IOStatus result;
  832. assert(lock != nullptr);
  833. delete lock;
  834. return result;
  835. }
  836. IOStatus WinFileSystem::GetTestDirectory(const IOOptions& opts,
  837. std::string* result,
  838. IODebugContext* dbg) {
  839. std::string output;
  840. const char* env = getenv("TEST_TMPDIR");
  841. if (env && env[0] != '\0') {
  842. output = env;
  843. } else {
  844. env = getenv("TMP");
  845. if (env && env[0] != '\0') {
  846. output = env;
  847. } else {
  848. output = "c:\\tmp";
  849. }
  850. }
  851. CreateDir(output, opts, dbg);
  852. output.append("\\testrocksdb-");
  853. output.append(std::to_string(GetCurrentProcessId()));
  854. CreateDir(output, opts, dbg);
  855. output.swap(*result);
  856. return IOStatus::OK();
  857. }
  858. IOStatus WinFileSystem::NewLogger(const std::string& fname,
  859. const IOOptions& /*opts*/,
  860. std::shared_ptr<Logger>* result,
  861. IODebugContext* /*dbg*/) {
  862. IOStatus s;
  863. result->reset();
  864. HANDLE hFile = 0;
  865. {
  866. IOSTATS_TIMER_GUARD(open_nanos);
  867. hFile = RX_CreateFile(
  868. RX_FN(fname).c_str(), GENERIC_WRITE,
  869. FILE_SHARE_READ | FILE_SHARE_DELETE, // In RocksDb log files are
  870. // renamed and deleted before
  871. // they are closed. This enables
  872. // doing so.
  873. NULL,
  874. CREATE_ALWAYS, // Original fopen mode is "w"
  875. FILE_ATTRIBUTE_NORMAL, NULL);
  876. }
  877. if (INVALID_HANDLE_VALUE == hFile) {
  878. auto lastError = GetLastError();
  879. s = IOErrorFromWindowsError("Failed to open LogFile" + fname, lastError);
  880. } else {
  881. {
  882. // With log files we want to set the true creation time as of now
  883. // because the system
  884. // for some reason caches the attributes of the previous file that just
  885. // been renamed from
  886. // this name so auto_roll_logger_test fails
  887. FILETIME ft;
  888. GetSystemTimeAsFileTime(&ft);
  889. // Set creation, last access and last write time to the same value
  890. SetFileTime(hFile, &ft, &ft, &ft);
  891. }
  892. result->reset(new WinLogger(&WinEnvThreads::gettid, clock_.get(), hFile));
  893. }
  894. return s;
  895. }
  896. IOStatus WinFileSystem::IsDirectory(const std::string& path,
  897. const IOOptions& /*opts*/, bool* is_dir,
  898. IODebugContext* /*dbg*/) {
  899. BOOL ret = RX_PathIsDirectory(RX_FN(path).c_str());
  900. if (is_dir) {
  901. *is_dir = ret ? true : false;
  902. }
  903. return IOStatus::OK();
  904. }
  905. Status WinEnvIO::GetHostName(char* name, uint64_t len) {
  906. Status s;
  907. DWORD nSize = static_cast<DWORD>(
  908. std::min<uint64_t>(len, std::numeric_limits<DWORD>::max()));
  909. if (!::GetComputerNameA(name, &nSize)) {
  910. auto lastError = GetLastError();
  911. s = IOErrorFromWindowsError("GetHostName", lastError);
  912. } else {
  913. name[nSize] = 0;
  914. }
  915. return s;
  916. }
  917. IOStatus WinFileSystem::GetAbsolutePath(const std::string& db_path,
  918. const IOOptions& /*options*/,
  919. std::string* output_path,
  920. IODebugContext* dbg) {
  921. // Check if we already have an absolute path
  922. // For test compatibility we will consider starting slash as an
  923. // absolute path
  924. if ((!db_path.empty() && (db_path[0] == '\\' || db_path[0] == '/')) ||
  925. !RX_PathIsRelative(RX_FN(db_path).c_str())) {
  926. *output_path = db_path;
  927. return IOStatus::OK();
  928. }
  929. RX_FILESTRING result;
  930. result.resize(MAX_PATH);
  931. // Hopefully no changes the current directory while we do this
  932. // however _getcwd also suffers from the same limitation
  933. DWORD len = RX_GetCurrentDirectory(MAX_PATH, &result[0]);
  934. if (len == 0) {
  935. auto lastError = GetLastError();
  936. return IOErrorFromWindowsError("Failed to get current working directory",
  937. lastError);
  938. }
  939. result.resize(len);
  940. std::string res = FN_TO_RX(result);
  941. res.swap(*output_path);
  942. return IOStatus::OK();
  943. }
  944. IOStatus WinFileSystem::GetFreeSpace(const std::string& path,
  945. const IOOptions& /*options*/,
  946. uint64_t* diskfree,
  947. IODebugContext* /*dbg*/) {
  948. assert(diskfree != nullptr);
  949. ULARGE_INTEGER freeBytes;
  950. BOOL f = RX_GetDiskFreeSpaceEx(RX_FN(path).c_str(), &freeBytes, NULL, NULL);
  951. if (f) {
  952. *diskfree = freeBytes.QuadPart;
  953. return IOStatus::OK();
  954. } else {
  955. DWORD lastError = GetLastError();
  956. return IOErrorFromWindowsError("Failed to get free space: " + path,
  957. lastError);
  958. }
  959. }
  960. FileOptions WinFileSystem::OptimizeForLogWrite(
  961. const FileOptions& file_options, const DBOptions& db_options) const {
  962. FileOptions optimized(file_options);
  963. // These two the same as default optimizations
  964. optimized.bytes_per_sync = db_options.wal_bytes_per_sync;
  965. optimized.writable_file_max_buffer_size =
  966. db_options.writable_file_max_buffer_size;
  967. // This adversely affects %999 on windows
  968. optimized.use_mmap_writes = false;
  969. // Direct writes will produce a huge perf impact on
  970. // Windows. Pre-allocate space for WAL.
  971. optimized.use_direct_writes = false;
  972. return optimized;
  973. }
  974. FileOptions WinFileSystem::OptimizeForManifestWrite(
  975. const FileOptions& options) const {
  976. FileOptions optimized(options);
  977. optimized.use_mmap_writes = false;
  978. optimized.use_direct_reads = false;
  979. return optimized;
  980. }
  981. FileOptions WinFileSystem::OptimizeForManifestRead(
  982. const FileOptions& file_options) const {
  983. FileOptions optimized(file_options);
  984. optimized.use_mmap_writes = false;
  985. optimized.use_direct_reads = false;
  986. return optimized;
  987. }
  988. // Returns true iff the named directory exists and is a directory.
  989. bool WinFileSystem::DirExists(const std::string& dname) {
  990. WIN32_FILE_ATTRIBUTE_DATA attrs;
  991. if (RX_GetFileAttributesEx(RX_FN(dname).c_str(), GetFileExInfoStandard,
  992. &attrs)) {
  993. return 0 != (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
  994. }
  995. return false;
  996. }
  997. size_t WinFileSystem::GetSectorSize(const std::string& fname) {
  998. size_t sector_size = kSectorSize;
  999. // obtain device handle
  1000. char devicename[7] = "\\\\.\\";
  1001. int erresult = 0;
  1002. if (RX_PathIsRelative(RX_FN(fname).c_str())) {
  1003. RX_FILESTRING rx_current_dir;
  1004. rx_current_dir.resize(MAX_PATH);
  1005. DWORD len = RX_GetCurrentDirectory(MAX_PATH, &rx_current_dir[0]);
  1006. if (len == 0) {
  1007. return sector_size;
  1008. }
  1009. rx_current_dir.resize(len);
  1010. std::string current_dir = FN_TO_RX(rx_current_dir);
  1011. erresult =
  1012. strncat_s(devicename, sizeof(devicename), current_dir.c_str(), 2);
  1013. } else {
  1014. erresult = strncat_s(devicename, sizeof(devicename), fname.c_str(), 2);
  1015. }
  1016. if (erresult) {
  1017. assert(false);
  1018. return sector_size;
  1019. }
  1020. HANDLE hDevice = CreateFile(devicename, 0, 0, nullptr, OPEN_EXISTING,
  1021. FILE_ATTRIBUTE_NORMAL, nullptr);
  1022. if (hDevice == INVALID_HANDLE_VALUE) {
  1023. return sector_size;
  1024. }
  1025. STORAGE_PROPERTY_QUERY spropertyquery;
  1026. spropertyquery.PropertyId = StorageAccessAlignmentProperty;
  1027. spropertyquery.QueryType = PropertyStandardQuery;
  1028. BYTE output_buffer[sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR)];
  1029. DWORD output_bytes = 0;
  1030. BOOL ret = DeviceIoControl(
  1031. hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &spropertyquery,
  1032. sizeof(spropertyquery), output_buffer,
  1033. sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), &output_bytes, nullptr);
  1034. if (ret) {
  1035. sector_size = ((STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR*)output_buffer)
  1036. ->BytesPerLogicalSector;
  1037. } else {
  1038. // many devices do not support StorageProcessAlignmentProperty. Any failure
  1039. // here and we fall back to logical alignment
  1040. DISK_GEOMETRY_EX geometry = {0};
  1041. ret = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, nullptr, 0,
  1042. &geometry, sizeof(geometry), &output_bytes, nullptr);
  1043. if (ret) {
  1044. sector_size = geometry.Geometry.BytesPerSector;
  1045. }
  1046. }
  1047. if (hDevice != INVALID_HANDLE_VALUE) {
  1048. CloseHandle(hDevice);
  1049. }
  1050. return sector_size;
  1051. }
  1052. ////////////////////////////////////////////////////////////////////////
  1053. // WinEnvThreads
  1054. WinEnvThreads::WinEnvThreads(Env* hosted_env)
  1055. : hosted_env_(hosted_env), thread_pools_(Env::Priority::TOTAL) {
  1056. for (int pool_id = 0; pool_id < Env::Priority::TOTAL; ++pool_id) {
  1057. thread_pools_[pool_id].SetThreadPriority(
  1058. static_cast<Env::Priority>(pool_id));
  1059. // This allows later initializing the thread-local-env of each thread.
  1060. thread_pools_[pool_id].SetHostEnv(hosted_env);
  1061. }
  1062. }
  1063. WinEnvThreads::~WinEnvThreads() {
  1064. WaitForJoin();
  1065. for (auto& thpool : thread_pools_) {
  1066. thpool.JoinAllThreads();
  1067. }
  1068. }
  1069. void WinEnvThreads::Schedule(void (*function)(void*), void* arg,
  1070. Env::Priority pri, void* tag,
  1071. void (*unschedFunction)(void* arg)) {
  1072. assert(pri >= Env::Priority::BOTTOM && pri <= Env::Priority::HIGH);
  1073. thread_pools_[pri].Schedule(function, arg, tag, unschedFunction);
  1074. }
  1075. int WinEnvThreads::UnSchedule(void* arg, Env::Priority pri) {
  1076. return thread_pools_[pri].UnSchedule(arg);
  1077. }
  1078. namespace {
  1079. struct StartThreadState {
  1080. void (*user_function)(void*);
  1081. void* arg;
  1082. };
  1083. void* StartThreadWrapper(void* arg) {
  1084. std::unique_ptr<StartThreadState> state(static_cast<StartThreadState*>(arg));
  1085. state->user_function(state->arg);
  1086. return nullptr;
  1087. }
  1088. } // namespace
  1089. void WinEnvThreads::StartThread(void (*function)(void* arg), void* arg) {
  1090. std::unique_ptr<StartThreadState> state(new StartThreadState);
  1091. state->user_function = function;
  1092. state->arg = arg;
  1093. try {
  1094. Thread th(&StartThreadWrapper, state.get());
  1095. state.release();
  1096. std::lock_guard<std::mutex> lg(mu_);
  1097. threads_to_join_.push_back(std::move(th));
  1098. } catch (const std::system_error& ex) {
  1099. WinthreadCall("start thread", ex.code());
  1100. }
  1101. }
  1102. void WinEnvThreads::WaitForJoin() {
  1103. for (auto& th : threads_to_join_) {
  1104. th.join();
  1105. }
  1106. threads_to_join_.clear();
  1107. }
  1108. unsigned int WinEnvThreads::GetThreadPoolQueueLen(Env::Priority pri) const {
  1109. assert(pri >= Env::Priority::BOTTOM && pri <= Env::Priority::HIGH);
  1110. return thread_pools_[pri].GetQueueLen();
  1111. }
  1112. int WinEnvThreads::ReserveThreads(int threads_to_reserved, Env::Priority pri) {
  1113. assert(pri >= Env::Priority::BOTTOM && pri <= Env::Priority::HIGH);
  1114. return thread_pools_[pri].ReserveThreads(threads_to_reserved);
  1115. }
  1116. int WinEnvThreads::ReleaseThreads(int threads_to_released, Env::Priority pri) {
  1117. assert(pri >= Env::Priority::BOTTOM && pri <= Env::Priority::HIGH);
  1118. return thread_pools_[pri].ReleaseThreads(threads_to_released);
  1119. }
  1120. uint64_t WinEnvThreads::gettid() {
  1121. uint64_t thread_id = GetCurrentThreadId();
  1122. return thread_id;
  1123. }
  1124. uint64_t WinEnvThreads::GetThreadID() const { return gettid(); }
  1125. void WinEnvThreads::SetBackgroundThreads(int num, Env::Priority pri) {
  1126. assert(pri >= Env::Priority::BOTTOM && pri <= Env::Priority::HIGH);
  1127. thread_pools_[pri].SetBackgroundThreads(num);
  1128. }
  1129. int WinEnvThreads::GetBackgroundThreads(Env::Priority pri) {
  1130. assert(pri >= Env::Priority::BOTTOM && pri <= Env::Priority::HIGH);
  1131. return thread_pools_[pri].GetBackgroundThreads();
  1132. }
  1133. void WinEnvThreads::IncBackgroundThreadsIfNeeded(int num, Env::Priority pri) {
  1134. assert(pri >= Env::Priority::BOTTOM && pri <= Env::Priority::HIGH);
  1135. thread_pools_[pri].IncBackgroundThreadsIfNeeded(num);
  1136. }
  1137. /////////////////////////////////////////////////////////////////////////
  1138. // WinEnv
  1139. WinEnv::WinEnv()
  1140. : CompositeEnv(WinFileSystem::Default(), WinClock::Default()),
  1141. winenv_io_(this),
  1142. winenv_threads_(this) {
  1143. // Protected member of the base class
  1144. thread_status_updater_ = CreateThreadStatusUpdater();
  1145. }
  1146. WinEnv::~WinEnv() {
  1147. // All threads must be joined before the deletion of
  1148. // thread_status_updater_.
  1149. delete thread_status_updater_;
  1150. }
  1151. Status WinEnv::GetThreadList(std::vector<ThreadStatus>* thread_list) {
  1152. assert(thread_status_updater_);
  1153. return thread_status_updater_->GetThreadList(thread_list);
  1154. }
  1155. Status WinEnv::GetHostName(char* name, uint64_t len) {
  1156. return winenv_io_.GetHostName(name, len);
  1157. }
  1158. void WinEnv::Schedule(void (*function)(void*), void* arg, Env::Priority pri,
  1159. void* tag, void (*unschedFunction)(void* arg)) {
  1160. return winenv_threads_.Schedule(function, arg, pri, tag, unschedFunction);
  1161. }
  1162. int WinEnv::UnSchedule(void* arg, Env::Priority pri) {
  1163. return winenv_threads_.UnSchedule(arg, pri);
  1164. }
  1165. void WinEnv::StartThread(void (*function)(void* arg), void* arg) {
  1166. return winenv_threads_.StartThread(function, arg);
  1167. }
  1168. void WinEnv::WaitForJoin() { return winenv_threads_.WaitForJoin(); }
  1169. unsigned int WinEnv::GetThreadPoolQueueLen(Env::Priority pri) const {
  1170. return winenv_threads_.GetThreadPoolQueueLen(pri);
  1171. }
  1172. int WinEnv::ReserveThreads(int threads_to_reserved, Env::Priority pri) {
  1173. return winenv_threads_.ReserveThreads(threads_to_reserved, pri);
  1174. }
  1175. int WinEnv::ReleaseThreads(int threads_to_released, Env::Priority pri) {
  1176. return winenv_threads_.ReleaseThreads(threads_to_released, pri);
  1177. }
  1178. uint64_t WinEnv::GetThreadID() const { return winenv_threads_.GetThreadID(); }
  1179. // Allow increasing the number of worker threads.
  1180. void WinEnv::SetBackgroundThreads(int num, Env::Priority pri) {
  1181. return winenv_threads_.SetBackgroundThreads(num, pri);
  1182. }
  1183. int WinEnv::GetBackgroundThreads(Env::Priority pri) {
  1184. return winenv_threads_.GetBackgroundThreads(pri);
  1185. }
  1186. void WinEnv::IncBackgroundThreadsIfNeeded(int num, Env::Priority pri) {
  1187. return winenv_threads_.IncBackgroundThreadsIfNeeded(num, pri);
  1188. }
  1189. } // namespace port
  1190. std::shared_ptr<FileSystem> FileSystem::Default() {
  1191. return port::WinFileSystem::Default();
  1192. }
  1193. const std::shared_ptr<SystemClock>& SystemClock::Default() {
  1194. STATIC_AVOID_DESTRUCTION(std::shared_ptr<SystemClock>, clock)
  1195. (std::make_shared<port::WinClock>());
  1196. return clock;
  1197. }
  1198. } // namespace ROCKSDB_NAMESPACE
  1199. #endif