xref: /aosp_15_r20/external/leveldb/util/env_windows.cc (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
1*9507f98cSAndroid Build Coastguard Worker // Copyright (c) 2018 The LevelDB Authors. All rights reserved.
2*9507f98cSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*9507f98cSAndroid Build Coastguard Worker // found in the LICENSE file. See the AUTHORS file for names of contributors.
4*9507f98cSAndroid Build Coastguard Worker 
5*9507f98cSAndroid Build Coastguard Worker // Prevent Windows headers from defining min/max macros and instead
6*9507f98cSAndroid Build Coastguard Worker // use STL.
7*9507f98cSAndroid Build Coastguard Worker #ifndef NOMINMAX
8*9507f98cSAndroid Build Coastguard Worker #define NOMINMAX
9*9507f98cSAndroid Build Coastguard Worker #endif  // ifndef NOMINMAX
10*9507f98cSAndroid Build Coastguard Worker 
11*9507f98cSAndroid Build Coastguard Worker #include <algorithm>
12*9507f98cSAndroid Build Coastguard Worker #include <atomic>
13*9507f98cSAndroid Build Coastguard Worker #include <chrono>
14*9507f98cSAndroid Build Coastguard Worker #include <condition_variable>
15*9507f98cSAndroid Build Coastguard Worker #include <cstddef>
16*9507f98cSAndroid Build Coastguard Worker #include <cstdint>
17*9507f98cSAndroid Build Coastguard Worker #include <cstdlib>
18*9507f98cSAndroid Build Coastguard Worker #include <cstring>
19*9507f98cSAndroid Build Coastguard Worker #include <memory>
20*9507f98cSAndroid Build Coastguard Worker #include <mutex>
21*9507f98cSAndroid Build Coastguard Worker #include <queue>
22*9507f98cSAndroid Build Coastguard Worker #include <sstream>
23*9507f98cSAndroid Build Coastguard Worker #include <string>
24*9507f98cSAndroid Build Coastguard Worker #include <vector>
25*9507f98cSAndroid Build Coastguard Worker 
26*9507f98cSAndroid Build Coastguard Worker #include "leveldb/env.h"
27*9507f98cSAndroid Build Coastguard Worker #include "leveldb/slice.h"
28*9507f98cSAndroid Build Coastguard Worker #include "port/port.h"
29*9507f98cSAndroid Build Coastguard Worker #include "port/thread_annotations.h"
30*9507f98cSAndroid Build Coastguard Worker #include "util/env_windows_test_helper.h"
31*9507f98cSAndroid Build Coastguard Worker #include "util/logging.h"
32*9507f98cSAndroid Build Coastguard Worker #include "util/mutexlock.h"
33*9507f98cSAndroid Build Coastguard Worker #include "util/windows_logger.h"
34*9507f98cSAndroid Build Coastguard Worker 
35*9507f98cSAndroid Build Coastguard Worker namespace leveldb {
36*9507f98cSAndroid Build Coastguard Worker 
37*9507f98cSAndroid Build Coastguard Worker namespace {
38*9507f98cSAndroid Build Coastguard Worker 
39*9507f98cSAndroid Build Coastguard Worker constexpr const size_t kWritableFileBufferSize = 65536;
40*9507f98cSAndroid Build Coastguard Worker 
41*9507f98cSAndroid Build Coastguard Worker // Up to 1000 mmaps for 64-bit binaries; none for 32-bit.
42*9507f98cSAndroid Build Coastguard Worker constexpr int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 1000 : 0;
43*9507f98cSAndroid Build Coastguard Worker 
44*9507f98cSAndroid Build Coastguard Worker // Can be set by by EnvWindowsTestHelper::SetReadOnlyMMapLimit().
45*9507f98cSAndroid Build Coastguard Worker int g_mmap_limit = kDefaultMmapLimit;
46*9507f98cSAndroid Build Coastguard Worker 
GetWindowsErrorMessage(DWORD error_code)47*9507f98cSAndroid Build Coastguard Worker std::string GetWindowsErrorMessage(DWORD error_code) {
48*9507f98cSAndroid Build Coastguard Worker   std::string message;
49*9507f98cSAndroid Build Coastguard Worker   char* error_text = nullptr;
50*9507f98cSAndroid Build Coastguard Worker   // Use MBCS version of FormatMessage to match return value.
51*9507f98cSAndroid Build Coastguard Worker   size_t error_text_size = ::FormatMessageA(
52*9507f98cSAndroid Build Coastguard Worker       FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
53*9507f98cSAndroid Build Coastguard Worker           FORMAT_MESSAGE_IGNORE_INSERTS,
54*9507f98cSAndroid Build Coastguard Worker       nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
55*9507f98cSAndroid Build Coastguard Worker       reinterpret_cast<char*>(&error_text), 0, nullptr);
56*9507f98cSAndroid Build Coastguard Worker   if (!error_text) {
57*9507f98cSAndroid Build Coastguard Worker     return message;
58*9507f98cSAndroid Build Coastguard Worker   }
59*9507f98cSAndroid Build Coastguard Worker   message.assign(error_text, error_text_size);
60*9507f98cSAndroid Build Coastguard Worker   ::LocalFree(error_text);
61*9507f98cSAndroid Build Coastguard Worker   return message;
62*9507f98cSAndroid Build Coastguard Worker }
63*9507f98cSAndroid Build Coastguard Worker 
WindowsError(const std::string & context,DWORD error_code)64*9507f98cSAndroid Build Coastguard Worker Status WindowsError(const std::string& context, DWORD error_code) {
65*9507f98cSAndroid Build Coastguard Worker   if (error_code == ERROR_FILE_NOT_FOUND || error_code == ERROR_PATH_NOT_FOUND)
66*9507f98cSAndroid Build Coastguard Worker     return Status::NotFound(context, GetWindowsErrorMessage(error_code));
67*9507f98cSAndroid Build Coastguard Worker   return Status::IOError(context, GetWindowsErrorMessage(error_code));
68*9507f98cSAndroid Build Coastguard Worker }
69*9507f98cSAndroid Build Coastguard Worker 
70*9507f98cSAndroid Build Coastguard Worker class ScopedHandle {
71*9507f98cSAndroid Build Coastguard Worker  public:
ScopedHandle(HANDLE handle)72*9507f98cSAndroid Build Coastguard Worker   ScopedHandle(HANDLE handle) : handle_(handle) {}
73*9507f98cSAndroid Build Coastguard Worker   ScopedHandle(const ScopedHandle&) = delete;
ScopedHandle(ScopedHandle && other)74*9507f98cSAndroid Build Coastguard Worker   ScopedHandle(ScopedHandle&& other) noexcept : handle_(other.Release()) {}
~ScopedHandle()75*9507f98cSAndroid Build Coastguard Worker   ~ScopedHandle() { Close(); }
76*9507f98cSAndroid Build Coastguard Worker 
77*9507f98cSAndroid Build Coastguard Worker   ScopedHandle& operator=(const ScopedHandle&) = delete;
78*9507f98cSAndroid Build Coastguard Worker 
operator =(ScopedHandle && rhs)79*9507f98cSAndroid Build Coastguard Worker   ScopedHandle& operator=(ScopedHandle&& rhs) noexcept {
80*9507f98cSAndroid Build Coastguard Worker     if (this != &rhs) handle_ = rhs.Release();
81*9507f98cSAndroid Build Coastguard Worker     return *this;
82*9507f98cSAndroid Build Coastguard Worker   }
83*9507f98cSAndroid Build Coastguard Worker 
Close()84*9507f98cSAndroid Build Coastguard Worker   bool Close() {
85*9507f98cSAndroid Build Coastguard Worker     if (!is_valid()) {
86*9507f98cSAndroid Build Coastguard Worker       return true;
87*9507f98cSAndroid Build Coastguard Worker     }
88*9507f98cSAndroid Build Coastguard Worker     HANDLE h = handle_;
89*9507f98cSAndroid Build Coastguard Worker     handle_ = INVALID_HANDLE_VALUE;
90*9507f98cSAndroid Build Coastguard Worker     return ::CloseHandle(h);
91*9507f98cSAndroid Build Coastguard Worker   }
92*9507f98cSAndroid Build Coastguard Worker 
is_valid() const93*9507f98cSAndroid Build Coastguard Worker   bool is_valid() const {
94*9507f98cSAndroid Build Coastguard Worker     return handle_ != INVALID_HANDLE_VALUE && handle_ != nullptr;
95*9507f98cSAndroid Build Coastguard Worker   }
96*9507f98cSAndroid Build Coastguard Worker 
get() const97*9507f98cSAndroid Build Coastguard Worker   HANDLE get() const { return handle_; }
98*9507f98cSAndroid Build Coastguard Worker 
Release()99*9507f98cSAndroid Build Coastguard Worker   HANDLE Release() {
100*9507f98cSAndroid Build Coastguard Worker     HANDLE h = handle_;
101*9507f98cSAndroid Build Coastguard Worker     handle_ = INVALID_HANDLE_VALUE;
102*9507f98cSAndroid Build Coastguard Worker     return h;
103*9507f98cSAndroid Build Coastguard Worker   }
104*9507f98cSAndroid Build Coastguard Worker 
105*9507f98cSAndroid Build Coastguard Worker  private:
106*9507f98cSAndroid Build Coastguard Worker   HANDLE handle_;
107*9507f98cSAndroid Build Coastguard Worker };
108*9507f98cSAndroid Build Coastguard Worker 
109*9507f98cSAndroid Build Coastguard Worker // Helper class to limit resource usage to avoid exhaustion.
110*9507f98cSAndroid Build Coastguard Worker // Currently used to limit read-only file descriptors and mmap file usage
111*9507f98cSAndroid Build Coastguard Worker // so that we do not run out of file descriptors or virtual memory, or run into
112*9507f98cSAndroid Build Coastguard Worker // kernel performance problems for very large databases.
113*9507f98cSAndroid Build Coastguard Worker class Limiter {
114*9507f98cSAndroid Build Coastguard Worker  public:
115*9507f98cSAndroid Build Coastguard Worker   // Limit maximum number of resources to |max_acquires|.
Limiter(int max_acquires)116*9507f98cSAndroid Build Coastguard Worker   Limiter(int max_acquires) : acquires_allowed_(max_acquires) {}
117*9507f98cSAndroid Build Coastguard Worker 
118*9507f98cSAndroid Build Coastguard Worker   Limiter(const Limiter&) = delete;
119*9507f98cSAndroid Build Coastguard Worker   Limiter operator=(const Limiter&) = delete;
120*9507f98cSAndroid Build Coastguard Worker 
121*9507f98cSAndroid Build Coastguard Worker   // If another resource is available, acquire it and return true.
122*9507f98cSAndroid Build Coastguard Worker   // Else return false.
Acquire()123*9507f98cSAndroid Build Coastguard Worker   bool Acquire() {
124*9507f98cSAndroid Build Coastguard Worker     int old_acquires_allowed =
125*9507f98cSAndroid Build Coastguard Worker         acquires_allowed_.fetch_sub(1, std::memory_order_relaxed);
126*9507f98cSAndroid Build Coastguard Worker 
127*9507f98cSAndroid Build Coastguard Worker     if (old_acquires_allowed > 0) return true;
128*9507f98cSAndroid Build Coastguard Worker 
129*9507f98cSAndroid Build Coastguard Worker     acquires_allowed_.fetch_add(1, std::memory_order_relaxed);
130*9507f98cSAndroid Build Coastguard Worker     return false;
131*9507f98cSAndroid Build Coastguard Worker   }
132*9507f98cSAndroid Build Coastguard Worker 
133*9507f98cSAndroid Build Coastguard Worker   // Release a resource acquired by a previous call to Acquire() that returned
134*9507f98cSAndroid Build Coastguard Worker   // true.
Release()135*9507f98cSAndroid Build Coastguard Worker   void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); }
136*9507f98cSAndroid Build Coastguard Worker 
137*9507f98cSAndroid Build Coastguard Worker  private:
138*9507f98cSAndroid Build Coastguard Worker   // The number of available resources.
139*9507f98cSAndroid Build Coastguard Worker   //
140*9507f98cSAndroid Build Coastguard Worker   // This is a counter and is not tied to the invariants of any other class, so
141*9507f98cSAndroid Build Coastguard Worker   // it can be operated on safely using std::memory_order_relaxed.
142*9507f98cSAndroid Build Coastguard Worker   std::atomic<int> acquires_allowed_;
143*9507f98cSAndroid Build Coastguard Worker };
144*9507f98cSAndroid Build Coastguard Worker 
145*9507f98cSAndroid Build Coastguard Worker class WindowsSequentialFile : public SequentialFile {
146*9507f98cSAndroid Build Coastguard Worker  public:
WindowsSequentialFile(std::string filename,ScopedHandle handle)147*9507f98cSAndroid Build Coastguard Worker   WindowsSequentialFile(std::string filename, ScopedHandle handle)
148*9507f98cSAndroid Build Coastguard Worker       : handle_(std::move(handle)), filename_(std::move(filename)) {}
~WindowsSequentialFile()149*9507f98cSAndroid Build Coastguard Worker   ~WindowsSequentialFile() override {}
150*9507f98cSAndroid Build Coastguard Worker 
Read(size_t n,Slice * result,char * scratch)151*9507f98cSAndroid Build Coastguard Worker   Status Read(size_t n, Slice* result, char* scratch) override {
152*9507f98cSAndroid Build Coastguard Worker     DWORD bytes_read;
153*9507f98cSAndroid Build Coastguard Worker     // DWORD is 32-bit, but size_t could technically be larger. However leveldb
154*9507f98cSAndroid Build Coastguard Worker     // files are limited to leveldb::Options::max_file_size which is clamped to
155*9507f98cSAndroid Build Coastguard Worker     // 1<<30 or 1 GiB.
156*9507f98cSAndroid Build Coastguard Worker     assert(n <= std::numeric_limits<DWORD>::max());
157*9507f98cSAndroid Build Coastguard Worker     if (!::ReadFile(handle_.get(), scratch, static_cast<DWORD>(n), &bytes_read,
158*9507f98cSAndroid Build Coastguard Worker                     nullptr)) {
159*9507f98cSAndroid Build Coastguard Worker       return WindowsError(filename_, ::GetLastError());
160*9507f98cSAndroid Build Coastguard Worker     }
161*9507f98cSAndroid Build Coastguard Worker 
162*9507f98cSAndroid Build Coastguard Worker     *result = Slice(scratch, bytes_read);
163*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
164*9507f98cSAndroid Build Coastguard Worker   }
165*9507f98cSAndroid Build Coastguard Worker 
Skip(uint64_t n)166*9507f98cSAndroid Build Coastguard Worker   Status Skip(uint64_t n) override {
167*9507f98cSAndroid Build Coastguard Worker     LARGE_INTEGER distance;
168*9507f98cSAndroid Build Coastguard Worker     distance.QuadPart = n;
169*9507f98cSAndroid Build Coastguard Worker     if (!::SetFilePointerEx(handle_.get(), distance, nullptr, FILE_CURRENT)) {
170*9507f98cSAndroid Build Coastguard Worker       return WindowsError(filename_, ::GetLastError());
171*9507f98cSAndroid Build Coastguard Worker     }
172*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
173*9507f98cSAndroid Build Coastguard Worker   }
174*9507f98cSAndroid Build Coastguard Worker 
175*9507f98cSAndroid Build Coastguard Worker  private:
176*9507f98cSAndroid Build Coastguard Worker   const ScopedHandle handle_;
177*9507f98cSAndroid Build Coastguard Worker   const std::string filename_;
178*9507f98cSAndroid Build Coastguard Worker };
179*9507f98cSAndroid Build Coastguard Worker 
180*9507f98cSAndroid Build Coastguard Worker class WindowsRandomAccessFile : public RandomAccessFile {
181*9507f98cSAndroid Build Coastguard Worker  public:
WindowsRandomAccessFile(std::string filename,ScopedHandle handle)182*9507f98cSAndroid Build Coastguard Worker   WindowsRandomAccessFile(std::string filename, ScopedHandle handle)
183*9507f98cSAndroid Build Coastguard Worker       : handle_(std::move(handle)), filename_(std::move(filename)) {}
184*9507f98cSAndroid Build Coastguard Worker 
185*9507f98cSAndroid Build Coastguard Worker   ~WindowsRandomAccessFile() override = default;
186*9507f98cSAndroid Build Coastguard Worker 
Read(uint64_t offset,size_t n,Slice * result,char * scratch) const187*9507f98cSAndroid Build Coastguard Worker   Status Read(uint64_t offset, size_t n, Slice* result,
188*9507f98cSAndroid Build Coastguard Worker               char* scratch) const override {
189*9507f98cSAndroid Build Coastguard Worker     DWORD bytes_read = 0;
190*9507f98cSAndroid Build Coastguard Worker     OVERLAPPED overlapped = {0};
191*9507f98cSAndroid Build Coastguard Worker 
192*9507f98cSAndroid Build Coastguard Worker     overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
193*9507f98cSAndroid Build Coastguard Worker     overlapped.Offset = static_cast<DWORD>(offset);
194*9507f98cSAndroid Build Coastguard Worker     if (!::ReadFile(handle_.get(), scratch, static_cast<DWORD>(n), &bytes_read,
195*9507f98cSAndroid Build Coastguard Worker                     &overlapped)) {
196*9507f98cSAndroid Build Coastguard Worker       DWORD error_code = ::GetLastError();
197*9507f98cSAndroid Build Coastguard Worker       if (error_code != ERROR_HANDLE_EOF) {
198*9507f98cSAndroid Build Coastguard Worker         *result = Slice(scratch, 0);
199*9507f98cSAndroid Build Coastguard Worker         return Status::IOError(filename_, GetWindowsErrorMessage(error_code));
200*9507f98cSAndroid Build Coastguard Worker       }
201*9507f98cSAndroid Build Coastguard Worker     }
202*9507f98cSAndroid Build Coastguard Worker 
203*9507f98cSAndroid Build Coastguard Worker     *result = Slice(scratch, bytes_read);
204*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
205*9507f98cSAndroid Build Coastguard Worker   }
206*9507f98cSAndroid Build Coastguard Worker 
207*9507f98cSAndroid Build Coastguard Worker  private:
208*9507f98cSAndroid Build Coastguard Worker   const ScopedHandle handle_;
209*9507f98cSAndroid Build Coastguard Worker   const std::string filename_;
210*9507f98cSAndroid Build Coastguard Worker };
211*9507f98cSAndroid Build Coastguard Worker 
212*9507f98cSAndroid Build Coastguard Worker class WindowsMmapReadableFile : public RandomAccessFile {
213*9507f98cSAndroid Build Coastguard Worker  public:
214*9507f98cSAndroid Build Coastguard Worker   // base[0,length-1] contains the mmapped contents of the file.
WindowsMmapReadableFile(std::string filename,char * mmap_base,size_t length,Limiter * mmap_limiter)215*9507f98cSAndroid Build Coastguard Worker   WindowsMmapReadableFile(std::string filename, char* mmap_base, size_t length,
216*9507f98cSAndroid Build Coastguard Worker                           Limiter* mmap_limiter)
217*9507f98cSAndroid Build Coastguard Worker       : mmap_base_(mmap_base),
218*9507f98cSAndroid Build Coastguard Worker         length_(length),
219*9507f98cSAndroid Build Coastguard Worker         mmap_limiter_(mmap_limiter),
220*9507f98cSAndroid Build Coastguard Worker         filename_(std::move(filename)) {}
221*9507f98cSAndroid Build Coastguard Worker 
~WindowsMmapReadableFile()222*9507f98cSAndroid Build Coastguard Worker   ~WindowsMmapReadableFile() override {
223*9507f98cSAndroid Build Coastguard Worker     ::UnmapViewOfFile(mmap_base_);
224*9507f98cSAndroid Build Coastguard Worker     mmap_limiter_->Release();
225*9507f98cSAndroid Build Coastguard Worker   }
226*9507f98cSAndroid Build Coastguard Worker 
Read(uint64_t offset,size_t n,Slice * result,char * scratch) const227*9507f98cSAndroid Build Coastguard Worker   Status Read(uint64_t offset, size_t n, Slice* result,
228*9507f98cSAndroid Build Coastguard Worker               char* scratch) const override {
229*9507f98cSAndroid Build Coastguard Worker     if (offset + n > length_) {
230*9507f98cSAndroid Build Coastguard Worker       *result = Slice();
231*9507f98cSAndroid Build Coastguard Worker       return WindowsError(filename_, ERROR_INVALID_PARAMETER);
232*9507f98cSAndroid Build Coastguard Worker     }
233*9507f98cSAndroid Build Coastguard Worker 
234*9507f98cSAndroid Build Coastguard Worker     *result = Slice(mmap_base_ + offset, n);
235*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
236*9507f98cSAndroid Build Coastguard Worker   }
237*9507f98cSAndroid Build Coastguard Worker 
238*9507f98cSAndroid Build Coastguard Worker  private:
239*9507f98cSAndroid Build Coastguard Worker   char* const mmap_base_;
240*9507f98cSAndroid Build Coastguard Worker   const size_t length_;
241*9507f98cSAndroid Build Coastguard Worker   Limiter* const mmap_limiter_;
242*9507f98cSAndroid Build Coastguard Worker   const std::string filename_;
243*9507f98cSAndroid Build Coastguard Worker };
244*9507f98cSAndroid Build Coastguard Worker 
245*9507f98cSAndroid Build Coastguard Worker class WindowsWritableFile : public WritableFile {
246*9507f98cSAndroid Build Coastguard Worker  public:
WindowsWritableFile(std::string filename,ScopedHandle handle)247*9507f98cSAndroid Build Coastguard Worker   WindowsWritableFile(std::string filename, ScopedHandle handle)
248*9507f98cSAndroid Build Coastguard Worker       : pos_(0), handle_(std::move(handle)), filename_(std::move(filename)) {}
249*9507f98cSAndroid Build Coastguard Worker 
250*9507f98cSAndroid Build Coastguard Worker   ~WindowsWritableFile() override = default;
251*9507f98cSAndroid Build Coastguard Worker 
Append(const Slice & data)252*9507f98cSAndroid Build Coastguard Worker   Status Append(const Slice& data) override {
253*9507f98cSAndroid Build Coastguard Worker     size_t write_size = data.size();
254*9507f98cSAndroid Build Coastguard Worker     const char* write_data = data.data();
255*9507f98cSAndroid Build Coastguard Worker 
256*9507f98cSAndroid Build Coastguard Worker     // Fit as much as possible into buffer.
257*9507f98cSAndroid Build Coastguard Worker     size_t copy_size = std::min(write_size, kWritableFileBufferSize - pos_);
258*9507f98cSAndroid Build Coastguard Worker     std::memcpy(buf_ + pos_, write_data, copy_size);
259*9507f98cSAndroid Build Coastguard Worker     write_data += copy_size;
260*9507f98cSAndroid Build Coastguard Worker     write_size -= copy_size;
261*9507f98cSAndroid Build Coastguard Worker     pos_ += copy_size;
262*9507f98cSAndroid Build Coastguard Worker     if (write_size == 0) {
263*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
264*9507f98cSAndroid Build Coastguard Worker     }
265*9507f98cSAndroid Build Coastguard Worker 
266*9507f98cSAndroid Build Coastguard Worker     // Can't fit in buffer, so need to do at least one write.
267*9507f98cSAndroid Build Coastguard Worker     Status status = FlushBuffer();
268*9507f98cSAndroid Build Coastguard Worker     if (!status.ok()) {
269*9507f98cSAndroid Build Coastguard Worker       return status;
270*9507f98cSAndroid Build Coastguard Worker     }
271*9507f98cSAndroid Build Coastguard Worker 
272*9507f98cSAndroid Build Coastguard Worker     // Small writes go to buffer, large writes are written directly.
273*9507f98cSAndroid Build Coastguard Worker     if (write_size < kWritableFileBufferSize) {
274*9507f98cSAndroid Build Coastguard Worker       std::memcpy(buf_, write_data, write_size);
275*9507f98cSAndroid Build Coastguard Worker       pos_ = write_size;
276*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
277*9507f98cSAndroid Build Coastguard Worker     }
278*9507f98cSAndroid Build Coastguard Worker     return WriteUnbuffered(write_data, write_size);
279*9507f98cSAndroid Build Coastguard Worker   }
280*9507f98cSAndroid Build Coastguard Worker 
Close()281*9507f98cSAndroid Build Coastguard Worker   Status Close() override {
282*9507f98cSAndroid Build Coastguard Worker     Status status = FlushBuffer();
283*9507f98cSAndroid Build Coastguard Worker     if (!handle_.Close() && status.ok()) {
284*9507f98cSAndroid Build Coastguard Worker       status = WindowsError(filename_, ::GetLastError());
285*9507f98cSAndroid Build Coastguard Worker     }
286*9507f98cSAndroid Build Coastguard Worker     return status;
287*9507f98cSAndroid Build Coastguard Worker   }
288*9507f98cSAndroid Build Coastguard Worker 
Flush()289*9507f98cSAndroid Build Coastguard Worker   Status Flush() override { return FlushBuffer(); }
290*9507f98cSAndroid Build Coastguard Worker 
Sync()291*9507f98cSAndroid Build Coastguard Worker   Status Sync() override {
292*9507f98cSAndroid Build Coastguard Worker     // On Windows no need to sync parent directory. Its metadata will be updated
293*9507f98cSAndroid Build Coastguard Worker     // via the creation of the new file, without an explicit sync.
294*9507f98cSAndroid Build Coastguard Worker 
295*9507f98cSAndroid Build Coastguard Worker     Status status = FlushBuffer();
296*9507f98cSAndroid Build Coastguard Worker     if (!status.ok()) {
297*9507f98cSAndroid Build Coastguard Worker       return status;
298*9507f98cSAndroid Build Coastguard Worker     }
299*9507f98cSAndroid Build Coastguard Worker 
300*9507f98cSAndroid Build Coastguard Worker     if (!::FlushFileBuffers(handle_.get())) {
301*9507f98cSAndroid Build Coastguard Worker       return Status::IOError(filename_,
302*9507f98cSAndroid Build Coastguard Worker                              GetWindowsErrorMessage(::GetLastError()));
303*9507f98cSAndroid Build Coastguard Worker     }
304*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
305*9507f98cSAndroid Build Coastguard Worker   }
306*9507f98cSAndroid Build Coastguard Worker 
307*9507f98cSAndroid Build Coastguard Worker  private:
FlushBuffer()308*9507f98cSAndroid Build Coastguard Worker   Status FlushBuffer() {
309*9507f98cSAndroid Build Coastguard Worker     Status status = WriteUnbuffered(buf_, pos_);
310*9507f98cSAndroid Build Coastguard Worker     pos_ = 0;
311*9507f98cSAndroid Build Coastguard Worker     return status;
312*9507f98cSAndroid Build Coastguard Worker   }
313*9507f98cSAndroid Build Coastguard Worker 
WriteUnbuffered(const char * data,size_t size)314*9507f98cSAndroid Build Coastguard Worker   Status WriteUnbuffered(const char* data, size_t size) {
315*9507f98cSAndroid Build Coastguard Worker     DWORD bytes_written;
316*9507f98cSAndroid Build Coastguard Worker     if (!::WriteFile(handle_.get(), data, static_cast<DWORD>(size),
317*9507f98cSAndroid Build Coastguard Worker                      &bytes_written, nullptr)) {
318*9507f98cSAndroid Build Coastguard Worker       return Status::IOError(filename_,
319*9507f98cSAndroid Build Coastguard Worker                              GetWindowsErrorMessage(::GetLastError()));
320*9507f98cSAndroid Build Coastguard Worker     }
321*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
322*9507f98cSAndroid Build Coastguard Worker   }
323*9507f98cSAndroid Build Coastguard Worker 
324*9507f98cSAndroid Build Coastguard Worker   // buf_[0, pos_-1] contains data to be written to handle_.
325*9507f98cSAndroid Build Coastguard Worker   char buf_[kWritableFileBufferSize];
326*9507f98cSAndroid Build Coastguard Worker   size_t pos_;
327*9507f98cSAndroid Build Coastguard Worker 
328*9507f98cSAndroid Build Coastguard Worker   ScopedHandle handle_;
329*9507f98cSAndroid Build Coastguard Worker   const std::string filename_;
330*9507f98cSAndroid Build Coastguard Worker };
331*9507f98cSAndroid Build Coastguard Worker 
332*9507f98cSAndroid Build Coastguard Worker // Lock or unlock the entire file as specified by |lock|. Returns true
333*9507f98cSAndroid Build Coastguard Worker // when successful, false upon failure. Caller should call ::GetLastError()
334*9507f98cSAndroid Build Coastguard Worker // to determine cause of failure
LockOrUnlock(HANDLE handle,bool lock)335*9507f98cSAndroid Build Coastguard Worker bool LockOrUnlock(HANDLE handle, bool lock) {
336*9507f98cSAndroid Build Coastguard Worker   if (lock) {
337*9507f98cSAndroid Build Coastguard Worker     return ::LockFile(handle,
338*9507f98cSAndroid Build Coastguard Worker                       /*dwFileOffsetLow=*/0, /*dwFileOffsetHigh=*/0,
339*9507f98cSAndroid Build Coastguard Worker                       /*nNumberOfBytesToLockLow=*/MAXDWORD,
340*9507f98cSAndroid Build Coastguard Worker                       /*nNumberOfBytesToLockHigh=*/MAXDWORD);
341*9507f98cSAndroid Build Coastguard Worker   } else {
342*9507f98cSAndroid Build Coastguard Worker     return ::UnlockFile(handle,
343*9507f98cSAndroid Build Coastguard Worker                         /*dwFileOffsetLow=*/0, /*dwFileOffsetHigh=*/0,
344*9507f98cSAndroid Build Coastguard Worker                         /*nNumberOfBytesToLockLow=*/MAXDWORD,
345*9507f98cSAndroid Build Coastguard Worker                         /*nNumberOfBytesToLockHigh=*/MAXDWORD);
346*9507f98cSAndroid Build Coastguard Worker   }
347*9507f98cSAndroid Build Coastguard Worker }
348*9507f98cSAndroid Build Coastguard Worker 
349*9507f98cSAndroid Build Coastguard Worker class WindowsFileLock : public FileLock {
350*9507f98cSAndroid Build Coastguard Worker  public:
WindowsFileLock(ScopedHandle handle,std::string filename)351*9507f98cSAndroid Build Coastguard Worker   WindowsFileLock(ScopedHandle handle, std::string filename)
352*9507f98cSAndroid Build Coastguard Worker       : handle_(std::move(handle)), filename_(std::move(filename)) {}
353*9507f98cSAndroid Build Coastguard Worker 
handle() const354*9507f98cSAndroid Build Coastguard Worker   const ScopedHandle& handle() const { return handle_; }
filename() const355*9507f98cSAndroid Build Coastguard Worker   const std::string& filename() const { return filename_; }
356*9507f98cSAndroid Build Coastguard Worker 
357*9507f98cSAndroid Build Coastguard Worker  private:
358*9507f98cSAndroid Build Coastguard Worker   const ScopedHandle handle_;
359*9507f98cSAndroid Build Coastguard Worker   const std::string filename_;
360*9507f98cSAndroid Build Coastguard Worker };
361*9507f98cSAndroid Build Coastguard Worker 
362*9507f98cSAndroid Build Coastguard Worker class WindowsEnv : public Env {
363*9507f98cSAndroid Build Coastguard Worker  public:
364*9507f98cSAndroid Build Coastguard Worker   WindowsEnv();
~WindowsEnv()365*9507f98cSAndroid Build Coastguard Worker   ~WindowsEnv() override {
366*9507f98cSAndroid Build Coastguard Worker     static const char msg[] =
367*9507f98cSAndroid Build Coastguard Worker         "WindowsEnv singleton destroyed. Unsupported behavior!\n";
368*9507f98cSAndroid Build Coastguard Worker     std::fwrite(msg, 1, sizeof(msg), stderr);
369*9507f98cSAndroid Build Coastguard Worker     std::abort();
370*9507f98cSAndroid Build Coastguard Worker   }
371*9507f98cSAndroid Build Coastguard Worker 
NewSequentialFile(const std::string & filename,SequentialFile ** result)372*9507f98cSAndroid Build Coastguard Worker   Status NewSequentialFile(const std::string& filename,
373*9507f98cSAndroid Build Coastguard Worker                            SequentialFile** result) override {
374*9507f98cSAndroid Build Coastguard Worker     *result = nullptr;
375*9507f98cSAndroid Build Coastguard Worker     DWORD desired_access = GENERIC_READ;
376*9507f98cSAndroid Build Coastguard Worker     DWORD share_mode = FILE_SHARE_READ;
377*9507f98cSAndroid Build Coastguard Worker     ScopedHandle handle = ::CreateFileA(
378*9507f98cSAndroid Build Coastguard Worker         filename.c_str(), desired_access, share_mode,
379*9507f98cSAndroid Build Coastguard Worker         /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
380*9507f98cSAndroid Build Coastguard Worker         /*hTemplateFile=*/nullptr);
381*9507f98cSAndroid Build Coastguard Worker     if (!handle.is_valid()) {
382*9507f98cSAndroid Build Coastguard Worker       return WindowsError(filename, ::GetLastError());
383*9507f98cSAndroid Build Coastguard Worker     }
384*9507f98cSAndroid Build Coastguard Worker 
385*9507f98cSAndroid Build Coastguard Worker     *result = new WindowsSequentialFile(filename, std::move(handle));
386*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
387*9507f98cSAndroid Build Coastguard Worker   }
388*9507f98cSAndroid Build Coastguard Worker 
NewRandomAccessFile(const std::string & filename,RandomAccessFile ** result)389*9507f98cSAndroid Build Coastguard Worker   Status NewRandomAccessFile(const std::string& filename,
390*9507f98cSAndroid Build Coastguard Worker                              RandomAccessFile** result) override {
391*9507f98cSAndroid Build Coastguard Worker     *result = nullptr;
392*9507f98cSAndroid Build Coastguard Worker     DWORD desired_access = GENERIC_READ;
393*9507f98cSAndroid Build Coastguard Worker     DWORD share_mode = FILE_SHARE_READ;
394*9507f98cSAndroid Build Coastguard Worker     ScopedHandle handle =
395*9507f98cSAndroid Build Coastguard Worker         ::CreateFileA(filename.c_str(), desired_access, share_mode,
396*9507f98cSAndroid Build Coastguard Worker                       /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING,
397*9507f98cSAndroid Build Coastguard Worker                       FILE_ATTRIBUTE_READONLY,
398*9507f98cSAndroid Build Coastguard Worker                       /*hTemplateFile=*/nullptr);
399*9507f98cSAndroid Build Coastguard Worker     if (!handle.is_valid()) {
400*9507f98cSAndroid Build Coastguard Worker       return WindowsError(filename, ::GetLastError());
401*9507f98cSAndroid Build Coastguard Worker     }
402*9507f98cSAndroid Build Coastguard Worker     if (!mmap_limiter_.Acquire()) {
403*9507f98cSAndroid Build Coastguard Worker       *result = new WindowsRandomAccessFile(filename, std::move(handle));
404*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
405*9507f98cSAndroid Build Coastguard Worker     }
406*9507f98cSAndroid Build Coastguard Worker 
407*9507f98cSAndroid Build Coastguard Worker     LARGE_INTEGER file_size;
408*9507f98cSAndroid Build Coastguard Worker     Status status;
409*9507f98cSAndroid Build Coastguard Worker     if (!::GetFileSizeEx(handle.get(), &file_size)) {
410*9507f98cSAndroid Build Coastguard Worker       mmap_limiter_.Release();
411*9507f98cSAndroid Build Coastguard Worker       return WindowsError(filename, ::GetLastError());
412*9507f98cSAndroid Build Coastguard Worker     }
413*9507f98cSAndroid Build Coastguard Worker 
414*9507f98cSAndroid Build Coastguard Worker     ScopedHandle mapping =
415*9507f98cSAndroid Build Coastguard Worker         ::CreateFileMappingA(handle.get(),
416*9507f98cSAndroid Build Coastguard Worker                              /*security attributes=*/nullptr, PAGE_READONLY,
417*9507f98cSAndroid Build Coastguard Worker                              /*dwMaximumSizeHigh=*/0,
418*9507f98cSAndroid Build Coastguard Worker                              /*dwMaximumSizeLow=*/0,
419*9507f98cSAndroid Build Coastguard Worker                              /*lpName=*/nullptr);
420*9507f98cSAndroid Build Coastguard Worker     if (mapping.is_valid()) {
421*9507f98cSAndroid Build Coastguard Worker       void* mmap_base = ::MapViewOfFile(mapping.get(), FILE_MAP_READ,
422*9507f98cSAndroid Build Coastguard Worker                                         /*dwFileOffsetHigh=*/0,
423*9507f98cSAndroid Build Coastguard Worker                                         /*dwFileOffsetLow=*/0,
424*9507f98cSAndroid Build Coastguard Worker                                         /*dwNumberOfBytesToMap=*/0);
425*9507f98cSAndroid Build Coastguard Worker       if (mmap_base) {
426*9507f98cSAndroid Build Coastguard Worker         *result = new WindowsMmapReadableFile(
427*9507f98cSAndroid Build Coastguard Worker             filename, reinterpret_cast<char*>(mmap_base),
428*9507f98cSAndroid Build Coastguard Worker             static_cast<size_t>(file_size.QuadPart), &mmap_limiter_);
429*9507f98cSAndroid Build Coastguard Worker         return Status::OK();
430*9507f98cSAndroid Build Coastguard Worker       }
431*9507f98cSAndroid Build Coastguard Worker     }
432*9507f98cSAndroid Build Coastguard Worker     mmap_limiter_.Release();
433*9507f98cSAndroid Build Coastguard Worker     return WindowsError(filename, ::GetLastError());
434*9507f98cSAndroid Build Coastguard Worker   }
435*9507f98cSAndroid Build Coastguard Worker 
NewWritableFile(const std::string & filename,WritableFile ** result)436*9507f98cSAndroid Build Coastguard Worker   Status NewWritableFile(const std::string& filename,
437*9507f98cSAndroid Build Coastguard Worker                          WritableFile** result) override {
438*9507f98cSAndroid Build Coastguard Worker     DWORD desired_access = GENERIC_WRITE;
439*9507f98cSAndroid Build Coastguard Worker     DWORD share_mode = 0;  // Exclusive access.
440*9507f98cSAndroid Build Coastguard Worker     ScopedHandle handle = ::CreateFileA(
441*9507f98cSAndroid Build Coastguard Worker         filename.c_str(), desired_access, share_mode,
442*9507f98cSAndroid Build Coastguard Worker         /*lpSecurityAttributes=*/nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
443*9507f98cSAndroid Build Coastguard Worker         /*hTemplateFile=*/nullptr);
444*9507f98cSAndroid Build Coastguard Worker     if (!handle.is_valid()) {
445*9507f98cSAndroid Build Coastguard Worker       *result = nullptr;
446*9507f98cSAndroid Build Coastguard Worker       return WindowsError(filename, ::GetLastError());
447*9507f98cSAndroid Build Coastguard Worker     }
448*9507f98cSAndroid Build Coastguard Worker 
449*9507f98cSAndroid Build Coastguard Worker     *result = new WindowsWritableFile(filename, std::move(handle));
450*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
451*9507f98cSAndroid Build Coastguard Worker   }
452*9507f98cSAndroid Build Coastguard Worker 
NewAppendableFile(const std::string & filename,WritableFile ** result)453*9507f98cSAndroid Build Coastguard Worker   Status NewAppendableFile(const std::string& filename,
454*9507f98cSAndroid Build Coastguard Worker                            WritableFile** result) override {
455*9507f98cSAndroid Build Coastguard Worker     DWORD desired_access = FILE_APPEND_DATA;
456*9507f98cSAndroid Build Coastguard Worker     DWORD share_mode = 0;  // Exclusive access.
457*9507f98cSAndroid Build Coastguard Worker     ScopedHandle handle = ::CreateFileA(
458*9507f98cSAndroid Build Coastguard Worker         filename.c_str(), desired_access, share_mode,
459*9507f98cSAndroid Build Coastguard Worker         /*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
460*9507f98cSAndroid Build Coastguard Worker         /*hTemplateFile=*/nullptr);
461*9507f98cSAndroid Build Coastguard Worker     if (!handle.is_valid()) {
462*9507f98cSAndroid Build Coastguard Worker       *result = nullptr;
463*9507f98cSAndroid Build Coastguard Worker       return WindowsError(filename, ::GetLastError());
464*9507f98cSAndroid Build Coastguard Worker     }
465*9507f98cSAndroid Build Coastguard Worker 
466*9507f98cSAndroid Build Coastguard Worker     *result = new WindowsWritableFile(filename, std::move(handle));
467*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
468*9507f98cSAndroid Build Coastguard Worker   }
469*9507f98cSAndroid Build Coastguard Worker 
FileExists(const std::string & filename)470*9507f98cSAndroid Build Coastguard Worker   bool FileExists(const std::string& filename) override {
471*9507f98cSAndroid Build Coastguard Worker     return GetFileAttributesA(filename.c_str()) != INVALID_FILE_ATTRIBUTES;
472*9507f98cSAndroid Build Coastguard Worker   }
473*9507f98cSAndroid Build Coastguard Worker 
GetChildren(const std::string & directory_path,std::vector<std::string> * result)474*9507f98cSAndroid Build Coastguard Worker   Status GetChildren(const std::string& directory_path,
475*9507f98cSAndroid Build Coastguard Worker                      std::vector<std::string>* result) override {
476*9507f98cSAndroid Build Coastguard Worker     const std::string find_pattern = directory_path + "\\*";
477*9507f98cSAndroid Build Coastguard Worker     WIN32_FIND_DATAA find_data;
478*9507f98cSAndroid Build Coastguard Worker     HANDLE dir_handle = ::FindFirstFileA(find_pattern.c_str(), &find_data);
479*9507f98cSAndroid Build Coastguard Worker     if (dir_handle == INVALID_HANDLE_VALUE) {
480*9507f98cSAndroid Build Coastguard Worker       DWORD last_error = ::GetLastError();
481*9507f98cSAndroid Build Coastguard Worker       if (last_error == ERROR_FILE_NOT_FOUND) {
482*9507f98cSAndroid Build Coastguard Worker         return Status::OK();
483*9507f98cSAndroid Build Coastguard Worker       }
484*9507f98cSAndroid Build Coastguard Worker       return WindowsError(directory_path, last_error);
485*9507f98cSAndroid Build Coastguard Worker     }
486*9507f98cSAndroid Build Coastguard Worker     do {
487*9507f98cSAndroid Build Coastguard Worker       char base_name[_MAX_FNAME];
488*9507f98cSAndroid Build Coastguard Worker       char ext[_MAX_EXT];
489*9507f98cSAndroid Build Coastguard Worker 
490*9507f98cSAndroid Build Coastguard Worker       if (!_splitpath_s(find_data.cFileName, nullptr, 0, nullptr, 0, base_name,
491*9507f98cSAndroid Build Coastguard Worker                         ARRAYSIZE(base_name), ext, ARRAYSIZE(ext))) {
492*9507f98cSAndroid Build Coastguard Worker         result->emplace_back(std::string(base_name) + ext);
493*9507f98cSAndroid Build Coastguard Worker       }
494*9507f98cSAndroid Build Coastguard Worker     } while (::FindNextFileA(dir_handle, &find_data));
495*9507f98cSAndroid Build Coastguard Worker     DWORD last_error = ::GetLastError();
496*9507f98cSAndroid Build Coastguard Worker     ::FindClose(dir_handle);
497*9507f98cSAndroid Build Coastguard Worker     if (last_error != ERROR_NO_MORE_FILES) {
498*9507f98cSAndroid Build Coastguard Worker       return WindowsError(directory_path, last_error);
499*9507f98cSAndroid Build Coastguard Worker     }
500*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
501*9507f98cSAndroid Build Coastguard Worker   }
502*9507f98cSAndroid Build Coastguard Worker 
RemoveFile(const std::string & filename)503*9507f98cSAndroid Build Coastguard Worker   Status RemoveFile(const std::string& filename) override {
504*9507f98cSAndroid Build Coastguard Worker     if (!::DeleteFileA(filename.c_str())) {
505*9507f98cSAndroid Build Coastguard Worker       return WindowsError(filename, ::GetLastError());
506*9507f98cSAndroid Build Coastguard Worker     }
507*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
508*9507f98cSAndroid Build Coastguard Worker   }
509*9507f98cSAndroid Build Coastguard Worker 
CreateDir(const std::string & dirname)510*9507f98cSAndroid Build Coastguard Worker   Status CreateDir(const std::string& dirname) override {
511*9507f98cSAndroid Build Coastguard Worker     if (!::CreateDirectoryA(dirname.c_str(), nullptr)) {
512*9507f98cSAndroid Build Coastguard Worker       return WindowsError(dirname, ::GetLastError());
513*9507f98cSAndroid Build Coastguard Worker     }
514*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
515*9507f98cSAndroid Build Coastguard Worker   }
516*9507f98cSAndroid Build Coastguard Worker 
RemoveDir(const std::string & dirname)517*9507f98cSAndroid Build Coastguard Worker   Status RemoveDir(const std::string& dirname) override {
518*9507f98cSAndroid Build Coastguard Worker     if (!::RemoveDirectoryA(dirname.c_str())) {
519*9507f98cSAndroid Build Coastguard Worker       return WindowsError(dirname, ::GetLastError());
520*9507f98cSAndroid Build Coastguard Worker     }
521*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
522*9507f98cSAndroid Build Coastguard Worker   }
523*9507f98cSAndroid Build Coastguard Worker 
GetFileSize(const std::string & filename,uint64_t * size)524*9507f98cSAndroid Build Coastguard Worker   Status GetFileSize(const std::string& filename, uint64_t* size) override {
525*9507f98cSAndroid Build Coastguard Worker     WIN32_FILE_ATTRIBUTE_DATA file_attributes;
526*9507f98cSAndroid Build Coastguard Worker     if (!::GetFileAttributesExA(filename.c_str(), GetFileExInfoStandard,
527*9507f98cSAndroid Build Coastguard Worker                                 &file_attributes)) {
528*9507f98cSAndroid Build Coastguard Worker       return WindowsError(filename, ::GetLastError());
529*9507f98cSAndroid Build Coastguard Worker     }
530*9507f98cSAndroid Build Coastguard Worker     ULARGE_INTEGER file_size;
531*9507f98cSAndroid Build Coastguard Worker     file_size.HighPart = file_attributes.nFileSizeHigh;
532*9507f98cSAndroid Build Coastguard Worker     file_size.LowPart = file_attributes.nFileSizeLow;
533*9507f98cSAndroid Build Coastguard Worker     *size = file_size.QuadPart;
534*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
535*9507f98cSAndroid Build Coastguard Worker   }
536*9507f98cSAndroid Build Coastguard Worker 
RenameFile(const std::string & from,const std::string & to)537*9507f98cSAndroid Build Coastguard Worker   Status RenameFile(const std::string& from, const std::string& to) override {
538*9507f98cSAndroid Build Coastguard Worker     // Try a simple move first. It will only succeed when |to| doesn't already
539*9507f98cSAndroid Build Coastguard Worker     // exist.
540*9507f98cSAndroid Build Coastguard Worker     if (::MoveFileA(from.c_str(), to.c_str())) {
541*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
542*9507f98cSAndroid Build Coastguard Worker     }
543*9507f98cSAndroid Build Coastguard Worker     DWORD move_error = ::GetLastError();
544*9507f98cSAndroid Build Coastguard Worker 
545*9507f98cSAndroid Build Coastguard Worker     // Try the full-blown replace if the move fails, as ReplaceFile will only
546*9507f98cSAndroid Build Coastguard Worker     // succeed when |to| does exist. When writing to a network share, we may not
547*9507f98cSAndroid Build Coastguard Worker     // be able to change the ACLs. Ignore ACL errors then
548*9507f98cSAndroid Build Coastguard Worker     // (REPLACEFILE_IGNORE_MERGE_ERRORS).
549*9507f98cSAndroid Build Coastguard Worker     if (::ReplaceFileA(to.c_str(), from.c_str(), /*lpBackupFileName=*/nullptr,
550*9507f98cSAndroid Build Coastguard Worker                        REPLACEFILE_IGNORE_MERGE_ERRORS,
551*9507f98cSAndroid Build Coastguard Worker                        /*lpExclude=*/nullptr, /*lpReserved=*/nullptr)) {
552*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
553*9507f98cSAndroid Build Coastguard Worker     }
554*9507f98cSAndroid Build Coastguard Worker     DWORD replace_error = ::GetLastError();
555*9507f98cSAndroid Build Coastguard Worker     // In the case of FILE_ERROR_NOT_FOUND from ReplaceFile, it is likely that
556*9507f98cSAndroid Build Coastguard Worker     // |to| does not exist. In this case, the more relevant error comes from the
557*9507f98cSAndroid Build Coastguard Worker     // call to MoveFile.
558*9507f98cSAndroid Build Coastguard Worker     if (replace_error == ERROR_FILE_NOT_FOUND ||
559*9507f98cSAndroid Build Coastguard Worker         replace_error == ERROR_PATH_NOT_FOUND) {
560*9507f98cSAndroid Build Coastguard Worker       return WindowsError(from, move_error);
561*9507f98cSAndroid Build Coastguard Worker     } else {
562*9507f98cSAndroid Build Coastguard Worker       return WindowsError(from, replace_error);
563*9507f98cSAndroid Build Coastguard Worker     }
564*9507f98cSAndroid Build Coastguard Worker   }
565*9507f98cSAndroid Build Coastguard Worker 
LockFile(const std::string & filename,FileLock ** lock)566*9507f98cSAndroid Build Coastguard Worker   Status LockFile(const std::string& filename, FileLock** lock) override {
567*9507f98cSAndroid Build Coastguard Worker     *lock = nullptr;
568*9507f98cSAndroid Build Coastguard Worker     Status result;
569*9507f98cSAndroid Build Coastguard Worker     ScopedHandle handle = ::CreateFileA(
570*9507f98cSAndroid Build Coastguard Worker         filename.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
571*9507f98cSAndroid Build Coastguard Worker         /*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
572*9507f98cSAndroid Build Coastguard Worker         nullptr);
573*9507f98cSAndroid Build Coastguard Worker     if (!handle.is_valid()) {
574*9507f98cSAndroid Build Coastguard Worker       result = WindowsError(filename, ::GetLastError());
575*9507f98cSAndroid Build Coastguard Worker     } else if (!LockOrUnlock(handle.get(), true)) {
576*9507f98cSAndroid Build Coastguard Worker       result = WindowsError("lock " + filename, ::GetLastError());
577*9507f98cSAndroid Build Coastguard Worker     } else {
578*9507f98cSAndroid Build Coastguard Worker       *lock = new WindowsFileLock(std::move(handle), filename);
579*9507f98cSAndroid Build Coastguard Worker     }
580*9507f98cSAndroid Build Coastguard Worker     return result;
581*9507f98cSAndroid Build Coastguard Worker   }
582*9507f98cSAndroid Build Coastguard Worker 
UnlockFile(FileLock * lock)583*9507f98cSAndroid Build Coastguard Worker   Status UnlockFile(FileLock* lock) override {
584*9507f98cSAndroid Build Coastguard Worker     WindowsFileLock* windows_file_lock =
585*9507f98cSAndroid Build Coastguard Worker         reinterpret_cast<WindowsFileLock*>(lock);
586*9507f98cSAndroid Build Coastguard Worker     if (!LockOrUnlock(windows_file_lock->handle().get(), false)) {
587*9507f98cSAndroid Build Coastguard Worker       return WindowsError("unlock " + windows_file_lock->filename(),
588*9507f98cSAndroid Build Coastguard Worker                           ::GetLastError());
589*9507f98cSAndroid Build Coastguard Worker     }
590*9507f98cSAndroid Build Coastguard Worker     delete windows_file_lock;
591*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
592*9507f98cSAndroid Build Coastguard Worker   }
593*9507f98cSAndroid Build Coastguard Worker 
594*9507f98cSAndroid Build Coastguard Worker   void Schedule(void (*background_work_function)(void* background_work_arg),
595*9507f98cSAndroid Build Coastguard Worker                 void* background_work_arg) override;
596*9507f98cSAndroid Build Coastguard Worker 
StartThread(void (* thread_main)(void * thread_main_arg),void * thread_main_arg)597*9507f98cSAndroid Build Coastguard Worker   void StartThread(void (*thread_main)(void* thread_main_arg),
598*9507f98cSAndroid Build Coastguard Worker                    void* thread_main_arg) override {
599*9507f98cSAndroid Build Coastguard Worker     std::thread new_thread(thread_main, thread_main_arg);
600*9507f98cSAndroid Build Coastguard Worker     new_thread.detach();
601*9507f98cSAndroid Build Coastguard Worker   }
602*9507f98cSAndroid Build Coastguard Worker 
GetTestDirectory(std::string * result)603*9507f98cSAndroid Build Coastguard Worker   Status GetTestDirectory(std::string* result) override {
604*9507f98cSAndroid Build Coastguard Worker     const char* env = getenv("TEST_TMPDIR");
605*9507f98cSAndroid Build Coastguard Worker     if (env && env[0] != '\0') {
606*9507f98cSAndroid Build Coastguard Worker       *result = env;
607*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
608*9507f98cSAndroid Build Coastguard Worker     }
609*9507f98cSAndroid Build Coastguard Worker 
610*9507f98cSAndroid Build Coastguard Worker     char tmp_path[MAX_PATH];
611*9507f98cSAndroid Build Coastguard Worker     if (!GetTempPathA(ARRAYSIZE(tmp_path), tmp_path)) {
612*9507f98cSAndroid Build Coastguard Worker       return WindowsError("GetTempPath", ::GetLastError());
613*9507f98cSAndroid Build Coastguard Worker     }
614*9507f98cSAndroid Build Coastguard Worker     std::stringstream ss;
615*9507f98cSAndroid Build Coastguard Worker     ss << tmp_path << "leveldbtest-" << std::this_thread::get_id();
616*9507f98cSAndroid Build Coastguard Worker     *result = ss.str();
617*9507f98cSAndroid Build Coastguard Worker 
618*9507f98cSAndroid Build Coastguard Worker     // Directory may already exist
619*9507f98cSAndroid Build Coastguard Worker     CreateDir(*result);
620*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
621*9507f98cSAndroid Build Coastguard Worker   }
622*9507f98cSAndroid Build Coastguard Worker 
NewLogger(const std::string & filename,Logger ** result)623*9507f98cSAndroid Build Coastguard Worker   Status NewLogger(const std::string& filename, Logger** result) override {
624*9507f98cSAndroid Build Coastguard Worker     std::FILE* fp = std::fopen(filename.c_str(), "w");
625*9507f98cSAndroid Build Coastguard Worker     if (fp == nullptr) {
626*9507f98cSAndroid Build Coastguard Worker       *result = nullptr;
627*9507f98cSAndroid Build Coastguard Worker       return WindowsError(filename, ::GetLastError());
628*9507f98cSAndroid Build Coastguard Worker     } else {
629*9507f98cSAndroid Build Coastguard Worker       *result = new WindowsLogger(fp);
630*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
631*9507f98cSAndroid Build Coastguard Worker     }
632*9507f98cSAndroid Build Coastguard Worker   }
633*9507f98cSAndroid Build Coastguard Worker 
NowMicros()634*9507f98cSAndroid Build Coastguard Worker   uint64_t NowMicros() override {
635*9507f98cSAndroid Build Coastguard Worker     // GetSystemTimeAsFileTime typically has a resolution of 10-20 msec.
636*9507f98cSAndroid Build Coastguard Worker     // TODO(cmumford): Switch to GetSystemTimePreciseAsFileTime which is
637*9507f98cSAndroid Build Coastguard Worker     // available in Windows 8 and later.
638*9507f98cSAndroid Build Coastguard Worker     FILETIME ft;
639*9507f98cSAndroid Build Coastguard Worker     ::GetSystemTimeAsFileTime(&ft);
640*9507f98cSAndroid Build Coastguard Worker     // Each tick represents a 100-nanosecond intervals since January 1, 1601
641*9507f98cSAndroid Build Coastguard Worker     // (UTC).
642*9507f98cSAndroid Build Coastguard Worker     uint64_t num_ticks =
643*9507f98cSAndroid Build Coastguard Worker         (static_cast<uint64_t>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
644*9507f98cSAndroid Build Coastguard Worker     return num_ticks / 10;
645*9507f98cSAndroid Build Coastguard Worker   }
646*9507f98cSAndroid Build Coastguard Worker 
SleepForMicroseconds(int micros)647*9507f98cSAndroid Build Coastguard Worker   void SleepForMicroseconds(int micros) override {
648*9507f98cSAndroid Build Coastguard Worker     std::this_thread::sleep_for(std::chrono::microseconds(micros));
649*9507f98cSAndroid Build Coastguard Worker   }
650*9507f98cSAndroid Build Coastguard Worker 
651*9507f98cSAndroid Build Coastguard Worker  private:
652*9507f98cSAndroid Build Coastguard Worker   void BackgroundThreadMain();
653*9507f98cSAndroid Build Coastguard Worker 
BackgroundThreadEntryPoint(WindowsEnv * env)654*9507f98cSAndroid Build Coastguard Worker   static void BackgroundThreadEntryPoint(WindowsEnv* env) {
655*9507f98cSAndroid Build Coastguard Worker     env->BackgroundThreadMain();
656*9507f98cSAndroid Build Coastguard Worker   }
657*9507f98cSAndroid Build Coastguard Worker 
658*9507f98cSAndroid Build Coastguard Worker   // Stores the work item data in a Schedule() call.
659*9507f98cSAndroid Build Coastguard Worker   //
660*9507f98cSAndroid Build Coastguard Worker   // Instances are constructed on the thread calling Schedule() and used on the
661*9507f98cSAndroid Build Coastguard Worker   // background thread.
662*9507f98cSAndroid Build Coastguard Worker   //
663*9507f98cSAndroid Build Coastguard Worker   // This structure is thread-safe beacuse it is immutable.
664*9507f98cSAndroid Build Coastguard Worker   struct BackgroundWorkItem {
BackgroundWorkItemleveldb::__anon0d865ec80111::WindowsEnv::BackgroundWorkItem665*9507f98cSAndroid Build Coastguard Worker     explicit BackgroundWorkItem(void (*function)(void* arg), void* arg)
666*9507f98cSAndroid Build Coastguard Worker         : function(function), arg(arg) {}
667*9507f98cSAndroid Build Coastguard Worker 
668*9507f98cSAndroid Build Coastguard Worker     void (*const function)(void*);
669*9507f98cSAndroid Build Coastguard Worker     void* const arg;
670*9507f98cSAndroid Build Coastguard Worker   };
671*9507f98cSAndroid Build Coastguard Worker 
672*9507f98cSAndroid Build Coastguard Worker   port::Mutex background_work_mutex_;
673*9507f98cSAndroid Build Coastguard Worker   port::CondVar background_work_cv_ GUARDED_BY(background_work_mutex_);
674*9507f98cSAndroid Build Coastguard Worker   bool started_background_thread_ GUARDED_BY(background_work_mutex_);
675*9507f98cSAndroid Build Coastguard Worker 
676*9507f98cSAndroid Build Coastguard Worker   std::queue<BackgroundWorkItem> background_work_queue_
677*9507f98cSAndroid Build Coastguard Worker       GUARDED_BY(background_work_mutex_);
678*9507f98cSAndroid Build Coastguard Worker 
679*9507f98cSAndroid Build Coastguard Worker   Limiter mmap_limiter_;  // Thread-safe.
680*9507f98cSAndroid Build Coastguard Worker };
681*9507f98cSAndroid Build Coastguard Worker 
682*9507f98cSAndroid Build Coastguard Worker // Return the maximum number of concurrent mmaps.
MaxMmaps()683*9507f98cSAndroid Build Coastguard Worker int MaxMmaps() { return g_mmap_limit; }
684*9507f98cSAndroid Build Coastguard Worker 
WindowsEnv()685*9507f98cSAndroid Build Coastguard Worker WindowsEnv::WindowsEnv()
686*9507f98cSAndroid Build Coastguard Worker     : background_work_cv_(&background_work_mutex_),
687*9507f98cSAndroid Build Coastguard Worker       started_background_thread_(false),
688*9507f98cSAndroid Build Coastguard Worker       mmap_limiter_(MaxMmaps()) {}
689*9507f98cSAndroid Build Coastguard Worker 
Schedule(void (* background_work_function)(void * background_work_arg),void * background_work_arg)690*9507f98cSAndroid Build Coastguard Worker void WindowsEnv::Schedule(
691*9507f98cSAndroid Build Coastguard Worker     void (*background_work_function)(void* background_work_arg),
692*9507f98cSAndroid Build Coastguard Worker     void* background_work_arg) {
693*9507f98cSAndroid Build Coastguard Worker   background_work_mutex_.Lock();
694*9507f98cSAndroid Build Coastguard Worker 
695*9507f98cSAndroid Build Coastguard Worker   // Start the background thread, if we haven't done so already.
696*9507f98cSAndroid Build Coastguard Worker   if (!started_background_thread_) {
697*9507f98cSAndroid Build Coastguard Worker     started_background_thread_ = true;
698*9507f98cSAndroid Build Coastguard Worker     std::thread background_thread(WindowsEnv::BackgroundThreadEntryPoint, this);
699*9507f98cSAndroid Build Coastguard Worker     background_thread.detach();
700*9507f98cSAndroid Build Coastguard Worker   }
701*9507f98cSAndroid Build Coastguard Worker 
702*9507f98cSAndroid Build Coastguard Worker   // If the queue is empty, the background thread may be waiting for work.
703*9507f98cSAndroid Build Coastguard Worker   if (background_work_queue_.empty()) {
704*9507f98cSAndroid Build Coastguard Worker     background_work_cv_.Signal();
705*9507f98cSAndroid Build Coastguard Worker   }
706*9507f98cSAndroid Build Coastguard Worker 
707*9507f98cSAndroid Build Coastguard Worker   background_work_queue_.emplace(background_work_function, background_work_arg);
708*9507f98cSAndroid Build Coastguard Worker   background_work_mutex_.Unlock();
709*9507f98cSAndroid Build Coastguard Worker }
710*9507f98cSAndroid Build Coastguard Worker 
BackgroundThreadMain()711*9507f98cSAndroid Build Coastguard Worker void WindowsEnv::BackgroundThreadMain() {
712*9507f98cSAndroid Build Coastguard Worker   while (true) {
713*9507f98cSAndroid Build Coastguard Worker     background_work_mutex_.Lock();
714*9507f98cSAndroid Build Coastguard Worker 
715*9507f98cSAndroid Build Coastguard Worker     // Wait until there is work to be done.
716*9507f98cSAndroid Build Coastguard Worker     while (background_work_queue_.empty()) {
717*9507f98cSAndroid Build Coastguard Worker       background_work_cv_.Wait();
718*9507f98cSAndroid Build Coastguard Worker     }
719*9507f98cSAndroid Build Coastguard Worker 
720*9507f98cSAndroid Build Coastguard Worker     assert(!background_work_queue_.empty());
721*9507f98cSAndroid Build Coastguard Worker     auto background_work_function = background_work_queue_.front().function;
722*9507f98cSAndroid Build Coastguard Worker     void* background_work_arg = background_work_queue_.front().arg;
723*9507f98cSAndroid Build Coastguard Worker     background_work_queue_.pop();
724*9507f98cSAndroid Build Coastguard Worker 
725*9507f98cSAndroid Build Coastguard Worker     background_work_mutex_.Unlock();
726*9507f98cSAndroid Build Coastguard Worker     background_work_function(background_work_arg);
727*9507f98cSAndroid Build Coastguard Worker   }
728*9507f98cSAndroid Build Coastguard Worker }
729*9507f98cSAndroid Build Coastguard Worker 
730*9507f98cSAndroid Build Coastguard Worker // Wraps an Env instance whose destructor is never created.
731*9507f98cSAndroid Build Coastguard Worker //
732*9507f98cSAndroid Build Coastguard Worker // Intended usage:
733*9507f98cSAndroid Build Coastguard Worker //   using PlatformSingletonEnv = SingletonEnv<PlatformEnv>;
734*9507f98cSAndroid Build Coastguard Worker //   void ConfigurePosixEnv(int param) {
735*9507f98cSAndroid Build Coastguard Worker //     PlatformSingletonEnv::AssertEnvNotInitialized();
736*9507f98cSAndroid Build Coastguard Worker //     // set global configuration flags.
737*9507f98cSAndroid Build Coastguard Worker //   }
738*9507f98cSAndroid Build Coastguard Worker //   Env* Env::Default() {
739*9507f98cSAndroid Build Coastguard Worker //     static PlatformSingletonEnv default_env;
740*9507f98cSAndroid Build Coastguard Worker //     return default_env.env();
741*9507f98cSAndroid Build Coastguard Worker //   }
742*9507f98cSAndroid Build Coastguard Worker template <typename EnvType>
743*9507f98cSAndroid Build Coastguard Worker class SingletonEnv {
744*9507f98cSAndroid Build Coastguard Worker  public:
SingletonEnv()745*9507f98cSAndroid Build Coastguard Worker   SingletonEnv() {
746*9507f98cSAndroid Build Coastguard Worker #if !defined(NDEBUG)
747*9507f98cSAndroid Build Coastguard Worker     env_initialized_.store(true, std::memory_order::memory_order_relaxed);
748*9507f98cSAndroid Build Coastguard Worker #endif  // !defined(NDEBUG)
749*9507f98cSAndroid Build Coastguard Worker     static_assert(sizeof(env_storage_) >= sizeof(EnvType),
750*9507f98cSAndroid Build Coastguard Worker                   "env_storage_ will not fit the Env");
751*9507f98cSAndroid Build Coastguard Worker     static_assert(alignof(decltype(env_storage_)) >= alignof(EnvType),
752*9507f98cSAndroid Build Coastguard Worker                   "env_storage_ does not meet the Env's alignment needs");
753*9507f98cSAndroid Build Coastguard Worker     new (&env_storage_) EnvType();
754*9507f98cSAndroid Build Coastguard Worker   }
755*9507f98cSAndroid Build Coastguard Worker   ~SingletonEnv() = default;
756*9507f98cSAndroid Build Coastguard Worker 
757*9507f98cSAndroid Build Coastguard Worker   SingletonEnv(const SingletonEnv&) = delete;
758*9507f98cSAndroid Build Coastguard Worker   SingletonEnv& operator=(const SingletonEnv&) = delete;
759*9507f98cSAndroid Build Coastguard Worker 
env()760*9507f98cSAndroid Build Coastguard Worker   Env* env() { return reinterpret_cast<Env*>(&env_storage_); }
761*9507f98cSAndroid Build Coastguard Worker 
AssertEnvNotInitialized()762*9507f98cSAndroid Build Coastguard Worker   static void AssertEnvNotInitialized() {
763*9507f98cSAndroid Build Coastguard Worker #if !defined(NDEBUG)
764*9507f98cSAndroid Build Coastguard Worker     assert(!env_initialized_.load(std::memory_order::memory_order_relaxed));
765*9507f98cSAndroid Build Coastguard Worker #endif  // !defined(NDEBUG)
766*9507f98cSAndroid Build Coastguard Worker   }
767*9507f98cSAndroid Build Coastguard Worker 
768*9507f98cSAndroid Build Coastguard Worker  private:
769*9507f98cSAndroid Build Coastguard Worker   typename std::aligned_storage<sizeof(EnvType), alignof(EnvType)>::type
770*9507f98cSAndroid Build Coastguard Worker       env_storage_;
771*9507f98cSAndroid Build Coastguard Worker #if !defined(NDEBUG)
772*9507f98cSAndroid Build Coastguard Worker   static std::atomic<bool> env_initialized_;
773*9507f98cSAndroid Build Coastguard Worker #endif  // !defined(NDEBUG)
774*9507f98cSAndroid Build Coastguard Worker };
775*9507f98cSAndroid Build Coastguard Worker 
776*9507f98cSAndroid Build Coastguard Worker #if !defined(NDEBUG)
777*9507f98cSAndroid Build Coastguard Worker template <typename EnvType>
778*9507f98cSAndroid Build Coastguard Worker std::atomic<bool> SingletonEnv<EnvType>::env_initialized_;
779*9507f98cSAndroid Build Coastguard Worker #endif  // !defined(NDEBUG)
780*9507f98cSAndroid Build Coastguard Worker 
781*9507f98cSAndroid Build Coastguard Worker using WindowsDefaultEnv = SingletonEnv<WindowsEnv>;
782*9507f98cSAndroid Build Coastguard Worker 
783*9507f98cSAndroid Build Coastguard Worker }  // namespace
784*9507f98cSAndroid Build Coastguard Worker 
SetReadOnlyMMapLimit(int limit)785*9507f98cSAndroid Build Coastguard Worker void EnvWindowsTestHelper::SetReadOnlyMMapLimit(int limit) {
786*9507f98cSAndroid Build Coastguard Worker   WindowsDefaultEnv::AssertEnvNotInitialized();
787*9507f98cSAndroid Build Coastguard Worker   g_mmap_limit = limit;
788*9507f98cSAndroid Build Coastguard Worker }
789*9507f98cSAndroid Build Coastguard Worker 
Default()790*9507f98cSAndroid Build Coastguard Worker Env* Env::Default() {
791*9507f98cSAndroid Build Coastguard Worker   static WindowsDefaultEnv env_container;
792*9507f98cSAndroid Build Coastguard Worker   return env_container.env();
793*9507f98cSAndroid Build Coastguard Worker }
794*9507f98cSAndroid Build Coastguard Worker 
795*9507f98cSAndroid Build Coastguard Worker }  // namespace leveldb
796