xref: /aosp_15_r20/external/leveldb/util/env_posix.cc (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
1*9507f98cSAndroid Build Coastguard Worker // Copyright (c) 2011 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 #include <dirent.h>
6*9507f98cSAndroid Build Coastguard Worker #include <fcntl.h>
7*9507f98cSAndroid Build Coastguard Worker #include <pthread.h>
8*9507f98cSAndroid Build Coastguard Worker #include <sys/mman.h>
9*9507f98cSAndroid Build Coastguard Worker #include <sys/resource.h>
10*9507f98cSAndroid Build Coastguard Worker #include <sys/stat.h>
11*9507f98cSAndroid Build Coastguard Worker #include <sys/time.h>
12*9507f98cSAndroid Build Coastguard Worker #include <sys/types.h>
13*9507f98cSAndroid Build Coastguard Worker #include <unistd.h>
14*9507f98cSAndroid Build Coastguard Worker 
15*9507f98cSAndroid Build Coastguard Worker #include <atomic>
16*9507f98cSAndroid Build Coastguard Worker #include <cerrno>
17*9507f98cSAndroid Build Coastguard Worker #include <cstddef>
18*9507f98cSAndroid Build Coastguard Worker #include <cstdint>
19*9507f98cSAndroid Build Coastguard Worker #include <cstdio>
20*9507f98cSAndroid Build Coastguard Worker #include <cstdlib>
21*9507f98cSAndroid Build Coastguard Worker #include <cstring>
22*9507f98cSAndroid Build Coastguard Worker #include <limits>
23*9507f98cSAndroid Build Coastguard Worker #include <queue>
24*9507f98cSAndroid Build Coastguard Worker #include <set>
25*9507f98cSAndroid Build Coastguard Worker #include <string>
26*9507f98cSAndroid Build Coastguard Worker #include <thread>
27*9507f98cSAndroid Build Coastguard Worker #include <type_traits>
28*9507f98cSAndroid Build Coastguard Worker #include <utility>
29*9507f98cSAndroid Build Coastguard Worker 
30*9507f98cSAndroid Build Coastguard Worker #include "leveldb/env.h"
31*9507f98cSAndroid Build Coastguard Worker #include "leveldb/slice.h"
32*9507f98cSAndroid Build Coastguard Worker #include "leveldb/status.h"
33*9507f98cSAndroid Build Coastguard Worker #include "port/port.h"
34*9507f98cSAndroid Build Coastguard Worker #include "port/thread_annotations.h"
35*9507f98cSAndroid Build Coastguard Worker #include "util/env_posix_test_helper.h"
36*9507f98cSAndroid Build Coastguard Worker #include "util/posix_logger.h"
37*9507f98cSAndroid Build Coastguard Worker 
38*9507f98cSAndroid Build Coastguard Worker namespace leveldb {
39*9507f98cSAndroid Build Coastguard Worker 
40*9507f98cSAndroid Build Coastguard Worker namespace {
41*9507f98cSAndroid Build Coastguard Worker 
42*9507f98cSAndroid Build Coastguard Worker // Set by EnvPosixTestHelper::SetReadOnlyMMapLimit() and MaxOpenFiles().
43*9507f98cSAndroid Build Coastguard Worker int g_open_read_only_file_limit = -1;
44*9507f98cSAndroid Build Coastguard Worker 
45*9507f98cSAndroid Build Coastguard Worker // Up to 1000 mmap regions for 64-bit binaries; none for 32-bit.
46*9507f98cSAndroid Build Coastguard Worker constexpr const int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 1000 : 0;
47*9507f98cSAndroid Build Coastguard Worker 
48*9507f98cSAndroid Build Coastguard Worker // Can be set using EnvPosixTestHelper::SetReadOnlyMMapLimit().
49*9507f98cSAndroid Build Coastguard Worker int g_mmap_limit = kDefaultMmapLimit;
50*9507f98cSAndroid Build Coastguard Worker 
51*9507f98cSAndroid Build Coastguard Worker // Common flags defined for all posix open operations
52*9507f98cSAndroid Build Coastguard Worker #if defined(HAVE_O_CLOEXEC)
53*9507f98cSAndroid Build Coastguard Worker constexpr const int kOpenBaseFlags = O_CLOEXEC;
54*9507f98cSAndroid Build Coastguard Worker #else
55*9507f98cSAndroid Build Coastguard Worker constexpr const int kOpenBaseFlags = 0;
56*9507f98cSAndroid Build Coastguard Worker #endif  // defined(HAVE_O_CLOEXEC)
57*9507f98cSAndroid Build Coastguard Worker 
58*9507f98cSAndroid Build Coastguard Worker constexpr const size_t kWritableFileBufferSize = 65536;
59*9507f98cSAndroid Build Coastguard Worker 
PosixError(const std::string & context,int error_number)60*9507f98cSAndroid Build Coastguard Worker Status PosixError(const std::string& context, int error_number) {
61*9507f98cSAndroid Build Coastguard Worker   if (error_number == ENOENT) {
62*9507f98cSAndroid Build Coastguard Worker     return Status::NotFound(context, std::strerror(error_number));
63*9507f98cSAndroid Build Coastguard Worker   } else {
64*9507f98cSAndroid Build Coastguard Worker     return Status::IOError(context, std::strerror(error_number));
65*9507f98cSAndroid Build Coastguard Worker   }
66*9507f98cSAndroid Build Coastguard Worker }
67*9507f98cSAndroid Build Coastguard Worker 
68*9507f98cSAndroid Build Coastguard Worker // Helper class to limit resource usage to avoid exhaustion.
69*9507f98cSAndroid Build Coastguard Worker // Currently used to limit read-only file descriptors and mmap file usage
70*9507f98cSAndroid Build Coastguard Worker // so that we do not run out of file descriptors or virtual memory, or run into
71*9507f98cSAndroid Build Coastguard Worker // kernel performance problems for very large databases.
72*9507f98cSAndroid Build Coastguard Worker class Limiter {
73*9507f98cSAndroid Build Coastguard Worker  public:
74*9507f98cSAndroid Build Coastguard Worker   // Limit maximum number of resources to |max_acquires|.
Limiter(int max_acquires)75*9507f98cSAndroid Build Coastguard Worker   Limiter(int max_acquires) : acquires_allowed_(max_acquires) {}
76*9507f98cSAndroid Build Coastguard Worker 
77*9507f98cSAndroid Build Coastguard Worker   Limiter(const Limiter&) = delete;
78*9507f98cSAndroid Build Coastguard Worker   Limiter operator=(const Limiter&) = delete;
79*9507f98cSAndroid Build Coastguard Worker 
80*9507f98cSAndroid Build Coastguard Worker   // If another resource is available, acquire it and return true.
81*9507f98cSAndroid Build Coastguard Worker   // Else return false.
Acquire()82*9507f98cSAndroid Build Coastguard Worker   bool Acquire() {
83*9507f98cSAndroid Build Coastguard Worker     int old_acquires_allowed =
84*9507f98cSAndroid Build Coastguard Worker         acquires_allowed_.fetch_sub(1, std::memory_order_relaxed);
85*9507f98cSAndroid Build Coastguard Worker 
86*9507f98cSAndroid Build Coastguard Worker     if (old_acquires_allowed > 0) return true;
87*9507f98cSAndroid Build Coastguard Worker 
88*9507f98cSAndroid Build Coastguard Worker     acquires_allowed_.fetch_add(1, std::memory_order_relaxed);
89*9507f98cSAndroid Build Coastguard Worker     return false;
90*9507f98cSAndroid Build Coastguard Worker   }
91*9507f98cSAndroid Build Coastguard Worker 
92*9507f98cSAndroid Build Coastguard Worker   // Release a resource acquired by a previous call to Acquire() that returned
93*9507f98cSAndroid Build Coastguard Worker   // true.
Release()94*9507f98cSAndroid Build Coastguard Worker   void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); }
95*9507f98cSAndroid Build Coastguard Worker 
96*9507f98cSAndroid Build Coastguard Worker  private:
97*9507f98cSAndroid Build Coastguard Worker   // The number of available resources.
98*9507f98cSAndroid Build Coastguard Worker   //
99*9507f98cSAndroid Build Coastguard Worker   // This is a counter and is not tied to the invariants of any other class, so
100*9507f98cSAndroid Build Coastguard Worker   // it can be operated on safely using std::memory_order_relaxed.
101*9507f98cSAndroid Build Coastguard Worker   std::atomic<int> acquires_allowed_;
102*9507f98cSAndroid Build Coastguard Worker };
103*9507f98cSAndroid Build Coastguard Worker 
104*9507f98cSAndroid Build Coastguard Worker // Implements sequential read access in a file using read().
105*9507f98cSAndroid Build Coastguard Worker //
106*9507f98cSAndroid Build Coastguard Worker // Instances of this class are thread-friendly but not thread-safe, as required
107*9507f98cSAndroid Build Coastguard Worker // by the SequentialFile API.
108*9507f98cSAndroid Build Coastguard Worker class PosixSequentialFile final : public SequentialFile {
109*9507f98cSAndroid Build Coastguard Worker  public:
PosixSequentialFile(std::string filename,int fd)110*9507f98cSAndroid Build Coastguard Worker   PosixSequentialFile(std::string filename, int fd)
111*9507f98cSAndroid Build Coastguard Worker       : fd_(fd), filename_(filename) {}
~PosixSequentialFile()112*9507f98cSAndroid Build Coastguard Worker   ~PosixSequentialFile() override { close(fd_); }
113*9507f98cSAndroid Build Coastguard Worker 
Read(size_t n,Slice * result,char * scratch)114*9507f98cSAndroid Build Coastguard Worker   Status Read(size_t n, Slice* result, char* scratch) override {
115*9507f98cSAndroid Build Coastguard Worker     Status status;
116*9507f98cSAndroid Build Coastguard Worker     while (true) {
117*9507f98cSAndroid Build Coastguard Worker       ::ssize_t read_size = ::read(fd_, scratch, n);
118*9507f98cSAndroid Build Coastguard Worker       if (read_size < 0) {  // Read error.
119*9507f98cSAndroid Build Coastguard Worker         if (errno == EINTR) {
120*9507f98cSAndroid Build Coastguard Worker           continue;  // Retry
121*9507f98cSAndroid Build Coastguard Worker         }
122*9507f98cSAndroid Build Coastguard Worker         status = PosixError(filename_, errno);
123*9507f98cSAndroid Build Coastguard Worker         break;
124*9507f98cSAndroid Build Coastguard Worker       }
125*9507f98cSAndroid Build Coastguard Worker       *result = Slice(scratch, read_size);
126*9507f98cSAndroid Build Coastguard Worker       break;
127*9507f98cSAndroid Build Coastguard Worker     }
128*9507f98cSAndroid Build Coastguard Worker     return status;
129*9507f98cSAndroid Build Coastguard Worker   }
130*9507f98cSAndroid Build Coastguard Worker 
Skip(uint64_t n)131*9507f98cSAndroid Build Coastguard Worker   Status Skip(uint64_t n) override {
132*9507f98cSAndroid Build Coastguard Worker     if (::lseek(fd_, n, SEEK_CUR) == static_cast<off_t>(-1)) {
133*9507f98cSAndroid Build Coastguard Worker       return PosixError(filename_, errno);
134*9507f98cSAndroid Build Coastguard Worker     }
135*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
136*9507f98cSAndroid Build Coastguard Worker   }
137*9507f98cSAndroid Build Coastguard Worker 
138*9507f98cSAndroid Build Coastguard Worker  private:
139*9507f98cSAndroid Build Coastguard Worker   const int fd_;
140*9507f98cSAndroid Build Coastguard Worker   const std::string filename_;
141*9507f98cSAndroid Build Coastguard Worker };
142*9507f98cSAndroid Build Coastguard Worker 
143*9507f98cSAndroid Build Coastguard Worker // Implements random read access in a file using pread().
144*9507f98cSAndroid Build Coastguard Worker //
145*9507f98cSAndroid Build Coastguard Worker // Instances of this class are thread-safe, as required by the RandomAccessFile
146*9507f98cSAndroid Build Coastguard Worker // API. Instances are immutable and Read() only calls thread-safe library
147*9507f98cSAndroid Build Coastguard Worker // functions.
148*9507f98cSAndroid Build Coastguard Worker class PosixRandomAccessFile final : public RandomAccessFile {
149*9507f98cSAndroid Build Coastguard Worker  public:
150*9507f98cSAndroid Build Coastguard Worker   // The new instance takes ownership of |fd|. |fd_limiter| must outlive this
151*9507f98cSAndroid Build Coastguard Worker   // instance, and will be used to determine if .
PosixRandomAccessFile(std::string filename,int fd,Limiter * fd_limiter)152*9507f98cSAndroid Build Coastguard Worker   PosixRandomAccessFile(std::string filename, int fd, Limiter* fd_limiter)
153*9507f98cSAndroid Build Coastguard Worker       : has_permanent_fd_(fd_limiter->Acquire()),
154*9507f98cSAndroid Build Coastguard Worker         fd_(has_permanent_fd_ ? fd : -1),
155*9507f98cSAndroid Build Coastguard Worker         fd_limiter_(fd_limiter),
156*9507f98cSAndroid Build Coastguard Worker         filename_(std::move(filename)) {
157*9507f98cSAndroid Build Coastguard Worker     if (!has_permanent_fd_) {
158*9507f98cSAndroid Build Coastguard Worker       assert(fd_ == -1);
159*9507f98cSAndroid Build Coastguard Worker       ::close(fd);  // The file will be opened on every read.
160*9507f98cSAndroid Build Coastguard Worker     }
161*9507f98cSAndroid Build Coastguard Worker   }
162*9507f98cSAndroid Build Coastguard Worker 
~PosixRandomAccessFile()163*9507f98cSAndroid Build Coastguard Worker   ~PosixRandomAccessFile() override {
164*9507f98cSAndroid Build Coastguard Worker     if (has_permanent_fd_) {
165*9507f98cSAndroid Build Coastguard Worker       assert(fd_ != -1);
166*9507f98cSAndroid Build Coastguard Worker       ::close(fd_);
167*9507f98cSAndroid Build Coastguard Worker       fd_limiter_->Release();
168*9507f98cSAndroid Build Coastguard Worker     }
169*9507f98cSAndroid Build Coastguard Worker   }
170*9507f98cSAndroid Build Coastguard Worker 
Read(uint64_t offset,size_t n,Slice * result,char * scratch) const171*9507f98cSAndroid Build Coastguard Worker   Status Read(uint64_t offset, size_t n, Slice* result,
172*9507f98cSAndroid Build Coastguard Worker               char* scratch) const override {
173*9507f98cSAndroid Build Coastguard Worker     int fd = fd_;
174*9507f98cSAndroid Build Coastguard Worker     if (!has_permanent_fd_) {
175*9507f98cSAndroid Build Coastguard Worker       fd = ::open(filename_.c_str(), O_RDONLY | kOpenBaseFlags);
176*9507f98cSAndroid Build Coastguard Worker       if (fd < 0) {
177*9507f98cSAndroid Build Coastguard Worker         return PosixError(filename_, errno);
178*9507f98cSAndroid Build Coastguard Worker       }
179*9507f98cSAndroid Build Coastguard Worker     }
180*9507f98cSAndroid Build Coastguard Worker 
181*9507f98cSAndroid Build Coastguard Worker     assert(fd != -1);
182*9507f98cSAndroid Build Coastguard Worker 
183*9507f98cSAndroid Build Coastguard Worker     Status status;
184*9507f98cSAndroid Build Coastguard Worker     ssize_t read_size = ::pread(fd, scratch, n, static_cast<off_t>(offset));
185*9507f98cSAndroid Build Coastguard Worker     *result = Slice(scratch, (read_size < 0) ? 0 : read_size);
186*9507f98cSAndroid Build Coastguard Worker     if (read_size < 0) {
187*9507f98cSAndroid Build Coastguard Worker       // An error: return a non-ok status.
188*9507f98cSAndroid Build Coastguard Worker       status = PosixError(filename_, errno);
189*9507f98cSAndroid Build Coastguard Worker     }
190*9507f98cSAndroid Build Coastguard Worker     if (!has_permanent_fd_) {
191*9507f98cSAndroid Build Coastguard Worker       // Close the temporary file descriptor opened earlier.
192*9507f98cSAndroid Build Coastguard Worker       assert(fd != fd_);
193*9507f98cSAndroid Build Coastguard Worker       ::close(fd);
194*9507f98cSAndroid Build Coastguard Worker     }
195*9507f98cSAndroid Build Coastguard Worker     return status;
196*9507f98cSAndroid Build Coastguard Worker   }
197*9507f98cSAndroid Build Coastguard Worker 
198*9507f98cSAndroid Build Coastguard Worker  private:
199*9507f98cSAndroid Build Coastguard Worker   const bool has_permanent_fd_;  // If false, the file is opened on every read.
200*9507f98cSAndroid Build Coastguard Worker   const int fd_;                 // -1 if has_permanent_fd_ is false.
201*9507f98cSAndroid Build Coastguard Worker   Limiter* const fd_limiter_;
202*9507f98cSAndroid Build Coastguard Worker   const std::string filename_;
203*9507f98cSAndroid Build Coastguard Worker };
204*9507f98cSAndroid Build Coastguard Worker 
205*9507f98cSAndroid Build Coastguard Worker // Implements random read access in a file using mmap().
206*9507f98cSAndroid Build Coastguard Worker //
207*9507f98cSAndroid Build Coastguard Worker // Instances of this class are thread-safe, as required by the RandomAccessFile
208*9507f98cSAndroid Build Coastguard Worker // API. Instances are immutable and Read() only calls thread-safe library
209*9507f98cSAndroid Build Coastguard Worker // functions.
210*9507f98cSAndroid Build Coastguard Worker class PosixMmapReadableFile final : public RandomAccessFile {
211*9507f98cSAndroid Build Coastguard Worker  public:
212*9507f98cSAndroid Build Coastguard Worker   // mmap_base[0, length-1] points to the memory-mapped contents of the file. It
213*9507f98cSAndroid Build Coastguard Worker   // must be the result of a successful call to mmap(). This instances takes
214*9507f98cSAndroid Build Coastguard Worker   // over the ownership of the region.
215*9507f98cSAndroid Build Coastguard Worker   //
216*9507f98cSAndroid Build Coastguard Worker   // |mmap_limiter| must outlive this instance. The caller must have already
217*9507f98cSAndroid Build Coastguard Worker   // aquired the right to use one mmap region, which will be released when this
218*9507f98cSAndroid Build Coastguard Worker   // instance is destroyed.
PosixMmapReadableFile(std::string filename,char * mmap_base,size_t length,Limiter * mmap_limiter)219*9507f98cSAndroid Build Coastguard Worker   PosixMmapReadableFile(std::string filename, char* mmap_base, size_t length,
220*9507f98cSAndroid Build Coastguard Worker                         Limiter* mmap_limiter)
221*9507f98cSAndroid Build Coastguard Worker       : mmap_base_(mmap_base),
222*9507f98cSAndroid Build Coastguard Worker         length_(length),
223*9507f98cSAndroid Build Coastguard Worker         mmap_limiter_(mmap_limiter),
224*9507f98cSAndroid Build Coastguard Worker         filename_(std::move(filename)) {}
225*9507f98cSAndroid Build Coastguard Worker 
~PosixMmapReadableFile()226*9507f98cSAndroid Build Coastguard Worker   ~PosixMmapReadableFile() override {
227*9507f98cSAndroid Build Coastguard Worker     ::munmap(static_cast<void*>(mmap_base_), length_);
228*9507f98cSAndroid Build Coastguard Worker     mmap_limiter_->Release();
229*9507f98cSAndroid Build Coastguard Worker   }
230*9507f98cSAndroid Build Coastguard Worker 
Read(uint64_t offset,size_t n,Slice * result,char * scratch) const231*9507f98cSAndroid Build Coastguard Worker   Status Read(uint64_t offset, size_t n, Slice* result,
232*9507f98cSAndroid Build Coastguard Worker               char* scratch) const override {
233*9507f98cSAndroid Build Coastguard Worker     if (offset + n > length_) {
234*9507f98cSAndroid Build Coastguard Worker       *result = Slice();
235*9507f98cSAndroid Build Coastguard Worker       return PosixError(filename_, EINVAL);
236*9507f98cSAndroid Build Coastguard Worker     }
237*9507f98cSAndroid Build Coastguard Worker 
238*9507f98cSAndroid Build Coastguard Worker     *result = Slice(mmap_base_ + offset, n);
239*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
240*9507f98cSAndroid Build Coastguard Worker   }
241*9507f98cSAndroid Build Coastguard Worker 
242*9507f98cSAndroid Build Coastguard Worker  private:
243*9507f98cSAndroid Build Coastguard Worker   char* const mmap_base_;
244*9507f98cSAndroid Build Coastguard Worker   const size_t length_;
245*9507f98cSAndroid Build Coastguard Worker   Limiter* const mmap_limiter_;
246*9507f98cSAndroid Build Coastguard Worker   const std::string filename_;
247*9507f98cSAndroid Build Coastguard Worker };
248*9507f98cSAndroid Build Coastguard Worker 
249*9507f98cSAndroid Build Coastguard Worker class PosixWritableFile final : public WritableFile {
250*9507f98cSAndroid Build Coastguard Worker  public:
PosixWritableFile(std::string filename,int fd)251*9507f98cSAndroid Build Coastguard Worker   PosixWritableFile(std::string filename, int fd)
252*9507f98cSAndroid Build Coastguard Worker       : pos_(0),
253*9507f98cSAndroid Build Coastguard Worker         fd_(fd),
254*9507f98cSAndroid Build Coastguard Worker         is_manifest_(IsManifest(filename)),
255*9507f98cSAndroid Build Coastguard Worker         filename_(std::move(filename)),
256*9507f98cSAndroid Build Coastguard Worker         dirname_(Dirname(filename_)) {}
257*9507f98cSAndroid Build Coastguard Worker 
~PosixWritableFile()258*9507f98cSAndroid Build Coastguard Worker   ~PosixWritableFile() override {
259*9507f98cSAndroid Build Coastguard Worker     if (fd_ >= 0) {
260*9507f98cSAndroid Build Coastguard Worker       // Ignoring any potential errors
261*9507f98cSAndroid Build Coastguard Worker       Close();
262*9507f98cSAndroid Build Coastguard Worker     }
263*9507f98cSAndroid Build Coastguard Worker   }
264*9507f98cSAndroid Build Coastguard Worker 
Append(const Slice & data)265*9507f98cSAndroid Build Coastguard Worker   Status Append(const Slice& data) override {
266*9507f98cSAndroid Build Coastguard Worker     size_t write_size = data.size();
267*9507f98cSAndroid Build Coastguard Worker     const char* write_data = data.data();
268*9507f98cSAndroid Build Coastguard Worker 
269*9507f98cSAndroid Build Coastguard Worker     // Fit as much as possible into buffer.
270*9507f98cSAndroid Build Coastguard Worker     size_t copy_size = std::min(write_size, kWritableFileBufferSize - pos_);
271*9507f98cSAndroid Build Coastguard Worker     std::memcpy(buf_ + pos_, write_data, copy_size);
272*9507f98cSAndroid Build Coastguard Worker     write_data += copy_size;
273*9507f98cSAndroid Build Coastguard Worker     write_size -= copy_size;
274*9507f98cSAndroid Build Coastguard Worker     pos_ += copy_size;
275*9507f98cSAndroid Build Coastguard Worker     if (write_size == 0) {
276*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
277*9507f98cSAndroid Build Coastguard Worker     }
278*9507f98cSAndroid Build Coastguard Worker 
279*9507f98cSAndroid Build Coastguard Worker     // Can't fit in buffer, so need to do at least one write.
280*9507f98cSAndroid Build Coastguard Worker     Status status = FlushBuffer();
281*9507f98cSAndroid Build Coastguard Worker     if (!status.ok()) {
282*9507f98cSAndroid Build Coastguard Worker       return status;
283*9507f98cSAndroid Build Coastguard Worker     }
284*9507f98cSAndroid Build Coastguard Worker 
285*9507f98cSAndroid Build Coastguard Worker     // Small writes go to buffer, large writes are written directly.
286*9507f98cSAndroid Build Coastguard Worker     if (write_size < kWritableFileBufferSize) {
287*9507f98cSAndroid Build Coastguard Worker       std::memcpy(buf_, write_data, write_size);
288*9507f98cSAndroid Build Coastguard Worker       pos_ = write_size;
289*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
290*9507f98cSAndroid Build Coastguard Worker     }
291*9507f98cSAndroid Build Coastguard Worker     return WriteUnbuffered(write_data, write_size);
292*9507f98cSAndroid Build Coastguard Worker   }
293*9507f98cSAndroid Build Coastguard Worker 
Close()294*9507f98cSAndroid Build Coastguard Worker   Status Close() override {
295*9507f98cSAndroid Build Coastguard Worker     Status status = FlushBuffer();
296*9507f98cSAndroid Build Coastguard Worker     const int close_result = ::close(fd_);
297*9507f98cSAndroid Build Coastguard Worker     if (close_result < 0 && status.ok()) {
298*9507f98cSAndroid Build Coastguard Worker       status = PosixError(filename_, errno);
299*9507f98cSAndroid Build Coastguard Worker     }
300*9507f98cSAndroid Build Coastguard Worker     fd_ = -1;
301*9507f98cSAndroid Build Coastguard Worker     return status;
302*9507f98cSAndroid Build Coastguard Worker   }
303*9507f98cSAndroid Build Coastguard Worker 
Flush()304*9507f98cSAndroid Build Coastguard Worker   Status Flush() override { return FlushBuffer(); }
305*9507f98cSAndroid Build Coastguard Worker 
Sync()306*9507f98cSAndroid Build Coastguard Worker   Status Sync() override {
307*9507f98cSAndroid Build Coastguard Worker     // Ensure new files referred to by the manifest are in the filesystem.
308*9507f98cSAndroid Build Coastguard Worker     //
309*9507f98cSAndroid Build Coastguard Worker     // This needs to happen before the manifest file is flushed to disk, to
310*9507f98cSAndroid Build Coastguard Worker     // avoid crashing in a state where the manifest refers to files that are not
311*9507f98cSAndroid Build Coastguard Worker     // yet on disk.
312*9507f98cSAndroid Build Coastguard Worker     Status status = SyncDirIfManifest();
313*9507f98cSAndroid Build Coastguard Worker     if (!status.ok()) {
314*9507f98cSAndroid Build Coastguard Worker       return status;
315*9507f98cSAndroid Build Coastguard Worker     }
316*9507f98cSAndroid Build Coastguard Worker 
317*9507f98cSAndroid Build Coastguard Worker     status = FlushBuffer();
318*9507f98cSAndroid Build Coastguard Worker     if (!status.ok()) {
319*9507f98cSAndroid Build Coastguard Worker       return status;
320*9507f98cSAndroid Build Coastguard Worker     }
321*9507f98cSAndroid Build Coastguard Worker 
322*9507f98cSAndroid Build Coastguard Worker     return SyncFd(fd_, filename_);
323*9507f98cSAndroid Build Coastguard Worker   }
324*9507f98cSAndroid Build Coastguard Worker 
325*9507f98cSAndroid Build Coastguard Worker  private:
FlushBuffer()326*9507f98cSAndroid Build Coastguard Worker   Status FlushBuffer() {
327*9507f98cSAndroid Build Coastguard Worker     Status status = WriteUnbuffered(buf_, pos_);
328*9507f98cSAndroid Build Coastguard Worker     pos_ = 0;
329*9507f98cSAndroid Build Coastguard Worker     return status;
330*9507f98cSAndroid Build Coastguard Worker   }
331*9507f98cSAndroid Build Coastguard Worker 
WriteUnbuffered(const char * data,size_t size)332*9507f98cSAndroid Build Coastguard Worker   Status WriteUnbuffered(const char* data, size_t size) {
333*9507f98cSAndroid Build Coastguard Worker     while (size > 0) {
334*9507f98cSAndroid Build Coastguard Worker       ssize_t write_result = ::write(fd_, data, size);
335*9507f98cSAndroid Build Coastguard Worker       if (write_result < 0) {
336*9507f98cSAndroid Build Coastguard Worker         if (errno == EINTR) {
337*9507f98cSAndroid Build Coastguard Worker           continue;  // Retry
338*9507f98cSAndroid Build Coastguard Worker         }
339*9507f98cSAndroid Build Coastguard Worker         return PosixError(filename_, errno);
340*9507f98cSAndroid Build Coastguard Worker       }
341*9507f98cSAndroid Build Coastguard Worker       data += write_result;
342*9507f98cSAndroid Build Coastguard Worker       size -= write_result;
343*9507f98cSAndroid Build Coastguard Worker     }
344*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
345*9507f98cSAndroid Build Coastguard Worker   }
346*9507f98cSAndroid Build Coastguard Worker 
SyncDirIfManifest()347*9507f98cSAndroid Build Coastguard Worker   Status SyncDirIfManifest() {
348*9507f98cSAndroid Build Coastguard Worker     Status status;
349*9507f98cSAndroid Build Coastguard Worker     if (!is_manifest_) {
350*9507f98cSAndroid Build Coastguard Worker       return status;
351*9507f98cSAndroid Build Coastguard Worker     }
352*9507f98cSAndroid Build Coastguard Worker 
353*9507f98cSAndroid Build Coastguard Worker     int fd = ::open(dirname_.c_str(), O_RDONLY | kOpenBaseFlags);
354*9507f98cSAndroid Build Coastguard Worker     if (fd < 0) {
355*9507f98cSAndroid Build Coastguard Worker       status = PosixError(dirname_, errno);
356*9507f98cSAndroid Build Coastguard Worker     } else {
357*9507f98cSAndroid Build Coastguard Worker       status = SyncFd(fd, dirname_);
358*9507f98cSAndroid Build Coastguard Worker       ::close(fd);
359*9507f98cSAndroid Build Coastguard Worker     }
360*9507f98cSAndroid Build Coastguard Worker     return status;
361*9507f98cSAndroid Build Coastguard Worker   }
362*9507f98cSAndroid Build Coastguard Worker 
363*9507f98cSAndroid Build Coastguard Worker   // Ensures that all the caches associated with the given file descriptor's
364*9507f98cSAndroid Build Coastguard Worker   // data are flushed all the way to durable media, and can withstand power
365*9507f98cSAndroid Build Coastguard Worker   // failures.
366*9507f98cSAndroid Build Coastguard Worker   //
367*9507f98cSAndroid Build Coastguard Worker   // The path argument is only used to populate the description string in the
368*9507f98cSAndroid Build Coastguard Worker   // returned Status if an error occurs.
SyncFd(int fd,const std::string & fd_path)369*9507f98cSAndroid Build Coastguard Worker   static Status SyncFd(int fd, const std::string& fd_path) {
370*9507f98cSAndroid Build Coastguard Worker #if HAVE_FULLFSYNC
371*9507f98cSAndroid Build Coastguard Worker     // On macOS and iOS, fsync() doesn't guarantee durability past power
372*9507f98cSAndroid Build Coastguard Worker     // failures. fcntl(F_FULLFSYNC) is required for that purpose. Some
373*9507f98cSAndroid Build Coastguard Worker     // filesystems don't support fcntl(F_FULLFSYNC), and require a fallback to
374*9507f98cSAndroid Build Coastguard Worker     // fsync().
375*9507f98cSAndroid Build Coastguard Worker     if (::fcntl(fd, F_FULLFSYNC) == 0) {
376*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
377*9507f98cSAndroid Build Coastguard Worker     }
378*9507f98cSAndroid Build Coastguard Worker #endif  // HAVE_FULLFSYNC
379*9507f98cSAndroid Build Coastguard Worker 
380*9507f98cSAndroid Build Coastguard Worker #if HAVE_FDATASYNC
381*9507f98cSAndroid Build Coastguard Worker     bool sync_success = ::fdatasync(fd) == 0;
382*9507f98cSAndroid Build Coastguard Worker #else
383*9507f98cSAndroid Build Coastguard Worker     bool sync_success = ::fsync(fd) == 0;
384*9507f98cSAndroid Build Coastguard Worker #endif  // HAVE_FDATASYNC
385*9507f98cSAndroid Build Coastguard Worker 
386*9507f98cSAndroid Build Coastguard Worker     if (sync_success) {
387*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
388*9507f98cSAndroid Build Coastguard Worker     }
389*9507f98cSAndroid Build Coastguard Worker     return PosixError(fd_path, errno);
390*9507f98cSAndroid Build Coastguard Worker   }
391*9507f98cSAndroid Build Coastguard Worker 
392*9507f98cSAndroid Build Coastguard Worker   // Returns the directory name in a path pointing to a file.
393*9507f98cSAndroid Build Coastguard Worker   //
394*9507f98cSAndroid Build Coastguard Worker   // Returns "." if the path does not contain any directory separator.
Dirname(const std::string & filename)395*9507f98cSAndroid Build Coastguard Worker   static std::string Dirname(const std::string& filename) {
396*9507f98cSAndroid Build Coastguard Worker     std::string::size_type separator_pos = filename.rfind('/');
397*9507f98cSAndroid Build Coastguard Worker     if (separator_pos == std::string::npos) {
398*9507f98cSAndroid Build Coastguard Worker       return std::string(".");
399*9507f98cSAndroid Build Coastguard Worker     }
400*9507f98cSAndroid Build Coastguard Worker     // The filename component should not contain a path separator. If it does,
401*9507f98cSAndroid Build Coastguard Worker     // the splitting was done incorrectly.
402*9507f98cSAndroid Build Coastguard Worker     assert(filename.find('/', separator_pos + 1) == std::string::npos);
403*9507f98cSAndroid Build Coastguard Worker 
404*9507f98cSAndroid Build Coastguard Worker     return filename.substr(0, separator_pos);
405*9507f98cSAndroid Build Coastguard Worker   }
406*9507f98cSAndroid Build Coastguard Worker 
407*9507f98cSAndroid Build Coastguard Worker   // Extracts the file name from a path pointing to a file.
408*9507f98cSAndroid Build Coastguard Worker   //
409*9507f98cSAndroid Build Coastguard Worker   // The returned Slice points to |filename|'s data buffer, so it is only valid
410*9507f98cSAndroid Build Coastguard Worker   // while |filename| is alive and unchanged.
Basename(const std::string & filename)411*9507f98cSAndroid Build Coastguard Worker   static Slice Basename(const std::string& filename) {
412*9507f98cSAndroid Build Coastguard Worker     std::string::size_type separator_pos = filename.rfind('/');
413*9507f98cSAndroid Build Coastguard Worker     if (separator_pos == std::string::npos) {
414*9507f98cSAndroid Build Coastguard Worker       return Slice(filename);
415*9507f98cSAndroid Build Coastguard Worker     }
416*9507f98cSAndroid Build Coastguard Worker     // The filename component should not contain a path separator. If it does,
417*9507f98cSAndroid Build Coastguard Worker     // the splitting was done incorrectly.
418*9507f98cSAndroid Build Coastguard Worker     assert(filename.find('/', separator_pos + 1) == std::string::npos);
419*9507f98cSAndroid Build Coastguard Worker 
420*9507f98cSAndroid Build Coastguard Worker     return Slice(filename.data() + separator_pos + 1,
421*9507f98cSAndroid Build Coastguard Worker                  filename.length() - separator_pos - 1);
422*9507f98cSAndroid Build Coastguard Worker   }
423*9507f98cSAndroid Build Coastguard Worker 
424*9507f98cSAndroid Build Coastguard Worker   // True if the given file is a manifest file.
IsManifest(const std::string & filename)425*9507f98cSAndroid Build Coastguard Worker   static bool IsManifest(const std::string& filename) {
426*9507f98cSAndroid Build Coastguard Worker     return Basename(filename).starts_with("MANIFEST");
427*9507f98cSAndroid Build Coastguard Worker   }
428*9507f98cSAndroid Build Coastguard Worker 
429*9507f98cSAndroid Build Coastguard Worker   // buf_[0, pos_ - 1] contains data to be written to fd_.
430*9507f98cSAndroid Build Coastguard Worker   char buf_[kWritableFileBufferSize];
431*9507f98cSAndroid Build Coastguard Worker   size_t pos_;
432*9507f98cSAndroid Build Coastguard Worker   int fd_;
433*9507f98cSAndroid Build Coastguard Worker 
434*9507f98cSAndroid Build Coastguard Worker   const bool is_manifest_;  // True if the file's name starts with MANIFEST.
435*9507f98cSAndroid Build Coastguard Worker   const std::string filename_;
436*9507f98cSAndroid Build Coastguard Worker   const std::string dirname_;  // The directory of filename_.
437*9507f98cSAndroid Build Coastguard Worker };
438*9507f98cSAndroid Build Coastguard Worker 
LockOrUnlock(int fd,bool lock)439*9507f98cSAndroid Build Coastguard Worker int LockOrUnlock(int fd, bool lock) {
440*9507f98cSAndroid Build Coastguard Worker   errno = 0;
441*9507f98cSAndroid Build Coastguard Worker   struct ::flock file_lock_info;
442*9507f98cSAndroid Build Coastguard Worker   std::memset(&file_lock_info, 0, sizeof(file_lock_info));
443*9507f98cSAndroid Build Coastguard Worker   file_lock_info.l_type = (lock ? F_WRLCK : F_UNLCK);
444*9507f98cSAndroid Build Coastguard Worker   file_lock_info.l_whence = SEEK_SET;
445*9507f98cSAndroid Build Coastguard Worker   file_lock_info.l_start = 0;
446*9507f98cSAndroid Build Coastguard Worker   file_lock_info.l_len = 0;  // Lock/unlock entire file.
447*9507f98cSAndroid Build Coastguard Worker   return ::fcntl(fd, F_SETLK, &file_lock_info);
448*9507f98cSAndroid Build Coastguard Worker }
449*9507f98cSAndroid Build Coastguard Worker 
450*9507f98cSAndroid Build Coastguard Worker // Instances are thread-safe because they are immutable.
451*9507f98cSAndroid Build Coastguard Worker class PosixFileLock : public FileLock {
452*9507f98cSAndroid Build Coastguard Worker  public:
PosixFileLock(int fd,std::string filename)453*9507f98cSAndroid Build Coastguard Worker   PosixFileLock(int fd, std::string filename)
454*9507f98cSAndroid Build Coastguard Worker       : fd_(fd), filename_(std::move(filename)) {}
455*9507f98cSAndroid Build Coastguard Worker 
fd() const456*9507f98cSAndroid Build Coastguard Worker   int fd() const { return fd_; }
filename() const457*9507f98cSAndroid Build Coastguard Worker   const std::string& filename() const { return filename_; }
458*9507f98cSAndroid Build Coastguard Worker 
459*9507f98cSAndroid Build Coastguard Worker  private:
460*9507f98cSAndroid Build Coastguard Worker   const int fd_;
461*9507f98cSAndroid Build Coastguard Worker   const std::string filename_;
462*9507f98cSAndroid Build Coastguard Worker };
463*9507f98cSAndroid Build Coastguard Worker 
464*9507f98cSAndroid Build Coastguard Worker // Tracks the files locked by PosixEnv::LockFile().
465*9507f98cSAndroid Build Coastguard Worker //
466*9507f98cSAndroid Build Coastguard Worker // We maintain a separate set instead of relying on fcntl(F_SETLK) because
467*9507f98cSAndroid Build Coastguard Worker // fcntl(F_SETLK) does not provide any protection against multiple uses from the
468*9507f98cSAndroid Build Coastguard Worker // same process.
469*9507f98cSAndroid Build Coastguard Worker //
470*9507f98cSAndroid Build Coastguard Worker // Instances are thread-safe because all member data is guarded by a mutex.
471*9507f98cSAndroid Build Coastguard Worker class PosixLockTable {
472*9507f98cSAndroid Build Coastguard Worker  public:
Insert(const std::string & fname)473*9507f98cSAndroid Build Coastguard Worker   bool Insert(const std::string& fname) LOCKS_EXCLUDED(mu_) {
474*9507f98cSAndroid Build Coastguard Worker     mu_.Lock();
475*9507f98cSAndroid Build Coastguard Worker     bool succeeded = locked_files_.insert(fname).second;
476*9507f98cSAndroid Build Coastguard Worker     mu_.Unlock();
477*9507f98cSAndroid Build Coastguard Worker     return succeeded;
478*9507f98cSAndroid Build Coastguard Worker   }
Remove(const std::string & fname)479*9507f98cSAndroid Build Coastguard Worker   void Remove(const std::string& fname) LOCKS_EXCLUDED(mu_) {
480*9507f98cSAndroid Build Coastguard Worker     mu_.Lock();
481*9507f98cSAndroid Build Coastguard Worker     locked_files_.erase(fname);
482*9507f98cSAndroid Build Coastguard Worker     mu_.Unlock();
483*9507f98cSAndroid Build Coastguard Worker   }
484*9507f98cSAndroid Build Coastguard Worker 
485*9507f98cSAndroid Build Coastguard Worker  private:
486*9507f98cSAndroid Build Coastguard Worker   port::Mutex mu_;
487*9507f98cSAndroid Build Coastguard Worker   std::set<std::string> locked_files_ GUARDED_BY(mu_);
488*9507f98cSAndroid Build Coastguard Worker };
489*9507f98cSAndroid Build Coastguard Worker 
490*9507f98cSAndroid Build Coastguard Worker class PosixEnv : public Env {
491*9507f98cSAndroid Build Coastguard Worker  public:
492*9507f98cSAndroid Build Coastguard Worker   PosixEnv();
~PosixEnv()493*9507f98cSAndroid Build Coastguard Worker   ~PosixEnv() override {
494*9507f98cSAndroid Build Coastguard Worker     static const char msg[] =
495*9507f98cSAndroid Build Coastguard Worker         "PosixEnv singleton destroyed. Unsupported behavior!\n";
496*9507f98cSAndroid Build Coastguard Worker     std::fwrite(msg, 1, sizeof(msg), stderr);
497*9507f98cSAndroid Build Coastguard Worker     std::abort();
498*9507f98cSAndroid Build Coastguard Worker   }
499*9507f98cSAndroid Build Coastguard Worker 
NewSequentialFile(const std::string & filename,SequentialFile ** result)500*9507f98cSAndroid Build Coastguard Worker   Status NewSequentialFile(const std::string& filename,
501*9507f98cSAndroid Build Coastguard Worker                            SequentialFile** result) override {
502*9507f98cSAndroid Build Coastguard Worker     int fd = ::open(filename.c_str(), O_RDONLY | kOpenBaseFlags);
503*9507f98cSAndroid Build Coastguard Worker     if (fd < 0) {
504*9507f98cSAndroid Build Coastguard Worker       *result = nullptr;
505*9507f98cSAndroid Build Coastguard Worker       return PosixError(filename, errno);
506*9507f98cSAndroid Build Coastguard Worker     }
507*9507f98cSAndroid Build Coastguard Worker 
508*9507f98cSAndroid Build Coastguard Worker     *result = new PosixSequentialFile(filename, fd);
509*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
510*9507f98cSAndroid Build Coastguard Worker   }
511*9507f98cSAndroid Build Coastguard Worker 
NewRandomAccessFile(const std::string & filename,RandomAccessFile ** result)512*9507f98cSAndroid Build Coastguard Worker   Status NewRandomAccessFile(const std::string& filename,
513*9507f98cSAndroid Build Coastguard Worker                              RandomAccessFile** result) override {
514*9507f98cSAndroid Build Coastguard Worker     *result = nullptr;
515*9507f98cSAndroid Build Coastguard Worker     int fd = ::open(filename.c_str(), O_RDONLY | kOpenBaseFlags);
516*9507f98cSAndroid Build Coastguard Worker     if (fd < 0) {
517*9507f98cSAndroid Build Coastguard Worker       return PosixError(filename, errno);
518*9507f98cSAndroid Build Coastguard Worker     }
519*9507f98cSAndroid Build Coastguard Worker 
520*9507f98cSAndroid Build Coastguard Worker     if (!mmap_limiter_.Acquire()) {
521*9507f98cSAndroid Build Coastguard Worker       *result = new PosixRandomAccessFile(filename, fd, &fd_limiter_);
522*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
523*9507f98cSAndroid Build Coastguard Worker     }
524*9507f98cSAndroid Build Coastguard Worker 
525*9507f98cSAndroid Build Coastguard Worker     uint64_t file_size;
526*9507f98cSAndroid Build Coastguard Worker     Status status = GetFileSize(filename, &file_size);
527*9507f98cSAndroid Build Coastguard Worker     if (status.ok()) {
528*9507f98cSAndroid Build Coastguard Worker       void* mmap_base =
529*9507f98cSAndroid Build Coastguard Worker           ::mmap(/*addr=*/nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0);
530*9507f98cSAndroid Build Coastguard Worker       if (mmap_base != MAP_FAILED) {
531*9507f98cSAndroid Build Coastguard Worker         *result = new PosixMmapReadableFile(filename,
532*9507f98cSAndroid Build Coastguard Worker                                             reinterpret_cast<char*>(mmap_base),
533*9507f98cSAndroid Build Coastguard Worker                                             file_size, &mmap_limiter_);
534*9507f98cSAndroid Build Coastguard Worker       } else {
535*9507f98cSAndroid Build Coastguard Worker         status = PosixError(filename, errno);
536*9507f98cSAndroid Build Coastguard Worker       }
537*9507f98cSAndroid Build Coastguard Worker     }
538*9507f98cSAndroid Build Coastguard Worker     ::close(fd);
539*9507f98cSAndroid Build Coastguard Worker     if (!status.ok()) {
540*9507f98cSAndroid Build Coastguard Worker       mmap_limiter_.Release();
541*9507f98cSAndroid Build Coastguard Worker     }
542*9507f98cSAndroid Build Coastguard Worker     return status;
543*9507f98cSAndroid Build Coastguard Worker   }
544*9507f98cSAndroid Build Coastguard Worker 
NewWritableFile(const std::string & filename,WritableFile ** result)545*9507f98cSAndroid Build Coastguard Worker   Status NewWritableFile(const std::string& filename,
546*9507f98cSAndroid Build Coastguard Worker                          WritableFile** result) override {
547*9507f98cSAndroid Build Coastguard Worker     int fd = ::open(filename.c_str(),
548*9507f98cSAndroid Build Coastguard Worker                     O_TRUNC | O_WRONLY | O_CREAT | kOpenBaseFlags, 0644);
549*9507f98cSAndroid Build Coastguard Worker     if (fd < 0) {
550*9507f98cSAndroid Build Coastguard Worker       *result = nullptr;
551*9507f98cSAndroid Build Coastguard Worker       return PosixError(filename, errno);
552*9507f98cSAndroid Build Coastguard Worker     }
553*9507f98cSAndroid Build Coastguard Worker 
554*9507f98cSAndroid Build Coastguard Worker     *result = new PosixWritableFile(filename, fd);
555*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
556*9507f98cSAndroid Build Coastguard Worker   }
557*9507f98cSAndroid Build Coastguard Worker 
NewAppendableFile(const std::string & filename,WritableFile ** result)558*9507f98cSAndroid Build Coastguard Worker   Status NewAppendableFile(const std::string& filename,
559*9507f98cSAndroid Build Coastguard Worker                            WritableFile** result) override {
560*9507f98cSAndroid Build Coastguard Worker     int fd = ::open(filename.c_str(),
561*9507f98cSAndroid Build Coastguard Worker                     O_APPEND | O_WRONLY | O_CREAT | kOpenBaseFlags, 0644);
562*9507f98cSAndroid Build Coastguard Worker     if (fd < 0) {
563*9507f98cSAndroid Build Coastguard Worker       *result = nullptr;
564*9507f98cSAndroid Build Coastguard Worker       return PosixError(filename, errno);
565*9507f98cSAndroid Build Coastguard Worker     }
566*9507f98cSAndroid Build Coastguard Worker 
567*9507f98cSAndroid Build Coastguard Worker     *result = new PosixWritableFile(filename, fd);
568*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
569*9507f98cSAndroid Build Coastguard Worker   }
570*9507f98cSAndroid Build Coastguard Worker 
FileExists(const std::string & filename)571*9507f98cSAndroid Build Coastguard Worker   bool FileExists(const std::string& filename) override {
572*9507f98cSAndroid Build Coastguard Worker     return ::access(filename.c_str(), F_OK) == 0;
573*9507f98cSAndroid Build Coastguard Worker   }
574*9507f98cSAndroid Build Coastguard Worker 
GetChildren(const std::string & directory_path,std::vector<std::string> * result)575*9507f98cSAndroid Build Coastguard Worker   Status GetChildren(const std::string& directory_path,
576*9507f98cSAndroid Build Coastguard Worker                      std::vector<std::string>* result) override {
577*9507f98cSAndroid Build Coastguard Worker     result->clear();
578*9507f98cSAndroid Build Coastguard Worker     ::DIR* dir = ::opendir(directory_path.c_str());
579*9507f98cSAndroid Build Coastguard Worker     if (dir == nullptr) {
580*9507f98cSAndroid Build Coastguard Worker       return PosixError(directory_path, errno);
581*9507f98cSAndroid Build Coastguard Worker     }
582*9507f98cSAndroid Build Coastguard Worker     struct ::dirent* entry;
583*9507f98cSAndroid Build Coastguard Worker     while ((entry = ::readdir(dir)) != nullptr) {
584*9507f98cSAndroid Build Coastguard Worker       result->emplace_back(entry->d_name);
585*9507f98cSAndroid Build Coastguard Worker     }
586*9507f98cSAndroid Build Coastguard Worker     ::closedir(dir);
587*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
588*9507f98cSAndroid Build Coastguard Worker   }
589*9507f98cSAndroid Build Coastguard Worker 
RemoveFile(const std::string & filename)590*9507f98cSAndroid Build Coastguard Worker   Status RemoveFile(const std::string& filename) override {
591*9507f98cSAndroid Build Coastguard Worker     if (::unlink(filename.c_str()) != 0) {
592*9507f98cSAndroid Build Coastguard Worker       return PosixError(filename, errno);
593*9507f98cSAndroid Build Coastguard Worker     }
594*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
595*9507f98cSAndroid Build Coastguard Worker   }
596*9507f98cSAndroid Build Coastguard Worker 
CreateDir(const std::string & dirname)597*9507f98cSAndroid Build Coastguard Worker   Status CreateDir(const std::string& dirname) override {
598*9507f98cSAndroid Build Coastguard Worker     if (::mkdir(dirname.c_str(), 0755) != 0) {
599*9507f98cSAndroid Build Coastguard Worker       return PosixError(dirname, errno);
600*9507f98cSAndroid Build Coastguard Worker     }
601*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
602*9507f98cSAndroid Build Coastguard Worker   }
603*9507f98cSAndroid Build Coastguard Worker 
RemoveDir(const std::string & dirname)604*9507f98cSAndroid Build Coastguard Worker   Status RemoveDir(const std::string& dirname) override {
605*9507f98cSAndroid Build Coastguard Worker     if (::rmdir(dirname.c_str()) != 0) {
606*9507f98cSAndroid Build Coastguard Worker       return PosixError(dirname, errno);
607*9507f98cSAndroid Build Coastguard Worker     }
608*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
609*9507f98cSAndroid Build Coastguard Worker   }
610*9507f98cSAndroid Build Coastguard Worker 
GetFileSize(const std::string & filename,uint64_t * size)611*9507f98cSAndroid Build Coastguard Worker   Status GetFileSize(const std::string& filename, uint64_t* size) override {
612*9507f98cSAndroid Build Coastguard Worker     struct ::stat file_stat;
613*9507f98cSAndroid Build Coastguard Worker     if (::stat(filename.c_str(), &file_stat) != 0) {
614*9507f98cSAndroid Build Coastguard Worker       *size = 0;
615*9507f98cSAndroid Build Coastguard Worker       return PosixError(filename, errno);
616*9507f98cSAndroid Build Coastguard Worker     }
617*9507f98cSAndroid Build Coastguard Worker     *size = file_stat.st_size;
618*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
619*9507f98cSAndroid Build Coastguard Worker   }
620*9507f98cSAndroid Build Coastguard Worker 
RenameFile(const std::string & from,const std::string & to)621*9507f98cSAndroid Build Coastguard Worker   Status RenameFile(const std::string& from, const std::string& to) override {
622*9507f98cSAndroid Build Coastguard Worker     if (std::rename(from.c_str(), to.c_str()) != 0) {
623*9507f98cSAndroid Build Coastguard Worker       return PosixError(from, errno);
624*9507f98cSAndroid Build Coastguard Worker     }
625*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
626*9507f98cSAndroid Build Coastguard Worker   }
627*9507f98cSAndroid Build Coastguard Worker 
LockFile(const std::string & filename,FileLock ** lock)628*9507f98cSAndroid Build Coastguard Worker   Status LockFile(const std::string& filename, FileLock** lock) override {
629*9507f98cSAndroid Build Coastguard Worker     *lock = nullptr;
630*9507f98cSAndroid Build Coastguard Worker 
631*9507f98cSAndroid Build Coastguard Worker     int fd = ::open(filename.c_str(), O_RDWR | O_CREAT | kOpenBaseFlags, 0644);
632*9507f98cSAndroid Build Coastguard Worker     if (fd < 0) {
633*9507f98cSAndroid Build Coastguard Worker       return PosixError(filename, errno);
634*9507f98cSAndroid Build Coastguard Worker     }
635*9507f98cSAndroid Build Coastguard Worker 
636*9507f98cSAndroid Build Coastguard Worker     if (!locks_.Insert(filename)) {
637*9507f98cSAndroid Build Coastguard Worker       ::close(fd);
638*9507f98cSAndroid Build Coastguard Worker       return Status::IOError("lock " + filename, "already held by process");
639*9507f98cSAndroid Build Coastguard Worker     }
640*9507f98cSAndroid Build Coastguard Worker 
641*9507f98cSAndroid Build Coastguard Worker     if (LockOrUnlock(fd, true) == -1) {
642*9507f98cSAndroid Build Coastguard Worker       int lock_errno = errno;
643*9507f98cSAndroid Build Coastguard Worker       ::close(fd);
644*9507f98cSAndroid Build Coastguard Worker       locks_.Remove(filename);
645*9507f98cSAndroid Build Coastguard Worker       return PosixError("lock " + filename, lock_errno);
646*9507f98cSAndroid Build Coastguard Worker     }
647*9507f98cSAndroid Build Coastguard Worker 
648*9507f98cSAndroid Build Coastguard Worker     *lock = new PosixFileLock(fd, filename);
649*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
650*9507f98cSAndroid Build Coastguard Worker   }
651*9507f98cSAndroid Build Coastguard Worker 
UnlockFile(FileLock * lock)652*9507f98cSAndroid Build Coastguard Worker   Status UnlockFile(FileLock* lock) override {
653*9507f98cSAndroid Build Coastguard Worker     PosixFileLock* posix_file_lock = static_cast<PosixFileLock*>(lock);
654*9507f98cSAndroid Build Coastguard Worker     if (LockOrUnlock(posix_file_lock->fd(), false) == -1) {
655*9507f98cSAndroid Build Coastguard Worker       return PosixError("unlock " + posix_file_lock->filename(), errno);
656*9507f98cSAndroid Build Coastguard Worker     }
657*9507f98cSAndroid Build Coastguard Worker     locks_.Remove(posix_file_lock->filename());
658*9507f98cSAndroid Build Coastguard Worker     ::close(posix_file_lock->fd());
659*9507f98cSAndroid Build Coastguard Worker     delete posix_file_lock;
660*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
661*9507f98cSAndroid Build Coastguard Worker   }
662*9507f98cSAndroid Build Coastguard Worker 
663*9507f98cSAndroid Build Coastguard Worker   void Schedule(void (*background_work_function)(void* background_work_arg),
664*9507f98cSAndroid Build Coastguard Worker                 void* background_work_arg) override;
665*9507f98cSAndroid Build Coastguard Worker 
StartThread(void (* thread_main)(void * thread_main_arg),void * thread_main_arg)666*9507f98cSAndroid Build Coastguard Worker   void StartThread(void (*thread_main)(void* thread_main_arg),
667*9507f98cSAndroid Build Coastguard Worker                    void* thread_main_arg) override {
668*9507f98cSAndroid Build Coastguard Worker     std::thread new_thread(thread_main, thread_main_arg);
669*9507f98cSAndroid Build Coastguard Worker     new_thread.detach();
670*9507f98cSAndroid Build Coastguard Worker   }
671*9507f98cSAndroid Build Coastguard Worker 
GetTestDirectory(std::string * result)672*9507f98cSAndroid Build Coastguard Worker   Status GetTestDirectory(std::string* result) override {
673*9507f98cSAndroid Build Coastguard Worker     const char* env = std::getenv("TEST_TMPDIR");
674*9507f98cSAndroid Build Coastguard Worker     if (env && env[0] != '\0') {
675*9507f98cSAndroid Build Coastguard Worker       *result = env;
676*9507f98cSAndroid Build Coastguard Worker     } else {
677*9507f98cSAndroid Build Coastguard Worker       char buf[100];
678*9507f98cSAndroid Build Coastguard Worker       std::snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d",
679*9507f98cSAndroid Build Coastguard Worker                     static_cast<int>(::geteuid()));
680*9507f98cSAndroid Build Coastguard Worker       *result = buf;
681*9507f98cSAndroid Build Coastguard Worker     }
682*9507f98cSAndroid Build Coastguard Worker 
683*9507f98cSAndroid Build Coastguard Worker     // The CreateDir status is ignored because the directory may already exist.
684*9507f98cSAndroid Build Coastguard Worker     CreateDir(*result);
685*9507f98cSAndroid Build Coastguard Worker 
686*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
687*9507f98cSAndroid Build Coastguard Worker   }
688*9507f98cSAndroid Build Coastguard Worker 
NewLogger(const std::string & filename,Logger ** result)689*9507f98cSAndroid Build Coastguard Worker   Status NewLogger(const std::string& filename, Logger** result) override {
690*9507f98cSAndroid Build Coastguard Worker     int fd = ::open(filename.c_str(),
691*9507f98cSAndroid Build Coastguard Worker                     O_APPEND | O_WRONLY | O_CREAT | kOpenBaseFlags, 0644);
692*9507f98cSAndroid Build Coastguard Worker     if (fd < 0) {
693*9507f98cSAndroid Build Coastguard Worker       *result = nullptr;
694*9507f98cSAndroid Build Coastguard Worker       return PosixError(filename, errno);
695*9507f98cSAndroid Build Coastguard Worker     }
696*9507f98cSAndroid Build Coastguard Worker 
697*9507f98cSAndroid Build Coastguard Worker     std::FILE* fp = ::fdopen(fd, "w");
698*9507f98cSAndroid Build Coastguard Worker     if (fp == nullptr) {
699*9507f98cSAndroid Build Coastguard Worker       ::close(fd);
700*9507f98cSAndroid Build Coastguard Worker       *result = nullptr;
701*9507f98cSAndroid Build Coastguard Worker       return PosixError(filename, errno);
702*9507f98cSAndroid Build Coastguard Worker     } else {
703*9507f98cSAndroid Build Coastguard Worker       *result = new PosixLogger(fp);
704*9507f98cSAndroid Build Coastguard Worker       return Status::OK();
705*9507f98cSAndroid Build Coastguard Worker     }
706*9507f98cSAndroid Build Coastguard Worker   }
707*9507f98cSAndroid Build Coastguard Worker 
NowMicros()708*9507f98cSAndroid Build Coastguard Worker   uint64_t NowMicros() override {
709*9507f98cSAndroid Build Coastguard Worker     static constexpr uint64_t kUsecondsPerSecond = 1000000;
710*9507f98cSAndroid Build Coastguard Worker     struct ::timeval tv;
711*9507f98cSAndroid Build Coastguard Worker     ::gettimeofday(&tv, nullptr);
712*9507f98cSAndroid Build Coastguard Worker     return static_cast<uint64_t>(tv.tv_sec) * kUsecondsPerSecond + tv.tv_usec;
713*9507f98cSAndroid Build Coastguard Worker   }
714*9507f98cSAndroid Build Coastguard Worker 
SleepForMicroseconds(int micros)715*9507f98cSAndroid Build Coastguard Worker   void SleepForMicroseconds(int micros) override {
716*9507f98cSAndroid Build Coastguard Worker     std::this_thread::sleep_for(std::chrono::microseconds(micros));
717*9507f98cSAndroid Build Coastguard Worker   }
718*9507f98cSAndroid Build Coastguard Worker 
719*9507f98cSAndroid Build Coastguard Worker  private:
720*9507f98cSAndroid Build Coastguard Worker   void BackgroundThreadMain();
721*9507f98cSAndroid Build Coastguard Worker 
BackgroundThreadEntryPoint(PosixEnv * env)722*9507f98cSAndroid Build Coastguard Worker   static void BackgroundThreadEntryPoint(PosixEnv* env) {
723*9507f98cSAndroid Build Coastguard Worker     env->BackgroundThreadMain();
724*9507f98cSAndroid Build Coastguard Worker   }
725*9507f98cSAndroid Build Coastguard Worker 
726*9507f98cSAndroid Build Coastguard Worker   // Stores the work item data in a Schedule() call.
727*9507f98cSAndroid Build Coastguard Worker   //
728*9507f98cSAndroid Build Coastguard Worker   // Instances are constructed on the thread calling Schedule() and used on the
729*9507f98cSAndroid Build Coastguard Worker   // background thread.
730*9507f98cSAndroid Build Coastguard Worker   //
731*9507f98cSAndroid Build Coastguard Worker   // This structure is thread-safe beacuse it is immutable.
732*9507f98cSAndroid Build Coastguard Worker   struct BackgroundWorkItem {
BackgroundWorkItemleveldb::__anon233a18300111::PosixEnv::BackgroundWorkItem733*9507f98cSAndroid Build Coastguard Worker     explicit BackgroundWorkItem(void (*function)(void* arg), void* arg)
734*9507f98cSAndroid Build Coastguard Worker         : function(function), arg(arg) {}
735*9507f98cSAndroid Build Coastguard Worker 
736*9507f98cSAndroid Build Coastguard Worker     void (*const function)(void*);
737*9507f98cSAndroid Build Coastguard Worker     void* const arg;
738*9507f98cSAndroid Build Coastguard Worker   };
739*9507f98cSAndroid Build Coastguard Worker 
740*9507f98cSAndroid Build Coastguard Worker   port::Mutex background_work_mutex_;
741*9507f98cSAndroid Build Coastguard Worker   port::CondVar background_work_cv_ GUARDED_BY(background_work_mutex_);
742*9507f98cSAndroid Build Coastguard Worker   bool started_background_thread_ GUARDED_BY(background_work_mutex_);
743*9507f98cSAndroid Build Coastguard Worker 
744*9507f98cSAndroid Build Coastguard Worker   std::queue<BackgroundWorkItem> background_work_queue_
745*9507f98cSAndroid Build Coastguard Worker       GUARDED_BY(background_work_mutex_);
746*9507f98cSAndroid Build Coastguard Worker 
747*9507f98cSAndroid Build Coastguard Worker   PosixLockTable locks_;  // Thread-safe.
748*9507f98cSAndroid Build Coastguard Worker   Limiter mmap_limiter_;  // Thread-safe.
749*9507f98cSAndroid Build Coastguard Worker   Limiter fd_limiter_;    // Thread-safe.
750*9507f98cSAndroid Build Coastguard Worker };
751*9507f98cSAndroid Build Coastguard Worker 
752*9507f98cSAndroid Build Coastguard Worker // Return the maximum number of concurrent mmaps.
MaxMmaps()753*9507f98cSAndroid Build Coastguard Worker int MaxMmaps() { return g_mmap_limit; }
754*9507f98cSAndroid Build Coastguard Worker 
755*9507f98cSAndroid Build Coastguard Worker // Return the maximum number of read-only files to keep open.
MaxOpenFiles()756*9507f98cSAndroid Build Coastguard Worker int MaxOpenFiles() {
757*9507f98cSAndroid Build Coastguard Worker   if (g_open_read_only_file_limit >= 0) {
758*9507f98cSAndroid Build Coastguard Worker     return g_open_read_only_file_limit;
759*9507f98cSAndroid Build Coastguard Worker   }
760*9507f98cSAndroid Build Coastguard Worker   struct ::rlimit rlim;
761*9507f98cSAndroid Build Coastguard Worker   if (::getrlimit(RLIMIT_NOFILE, &rlim)) {
762*9507f98cSAndroid Build Coastguard Worker     // getrlimit failed, fallback to hard-coded default.
763*9507f98cSAndroid Build Coastguard Worker     g_open_read_only_file_limit = 50;
764*9507f98cSAndroid Build Coastguard Worker   } else if (rlim.rlim_cur == RLIM_INFINITY) {
765*9507f98cSAndroid Build Coastguard Worker     g_open_read_only_file_limit = std::numeric_limits<int>::max();
766*9507f98cSAndroid Build Coastguard Worker   } else {
767*9507f98cSAndroid Build Coastguard Worker     // Allow use of 20% of available file descriptors for read-only files.
768*9507f98cSAndroid Build Coastguard Worker     g_open_read_only_file_limit = rlim.rlim_cur / 5;
769*9507f98cSAndroid Build Coastguard Worker   }
770*9507f98cSAndroid Build Coastguard Worker   return g_open_read_only_file_limit;
771*9507f98cSAndroid Build Coastguard Worker }
772*9507f98cSAndroid Build Coastguard Worker 
773*9507f98cSAndroid Build Coastguard Worker }  // namespace
774*9507f98cSAndroid Build Coastguard Worker 
PosixEnv()775*9507f98cSAndroid Build Coastguard Worker PosixEnv::PosixEnv()
776*9507f98cSAndroid Build Coastguard Worker     : background_work_cv_(&background_work_mutex_),
777*9507f98cSAndroid Build Coastguard Worker       started_background_thread_(false),
778*9507f98cSAndroid Build Coastguard Worker       mmap_limiter_(MaxMmaps()),
779*9507f98cSAndroid Build Coastguard Worker       fd_limiter_(MaxOpenFiles()) {}
780*9507f98cSAndroid Build Coastguard Worker 
Schedule(void (* background_work_function)(void * background_work_arg),void * background_work_arg)781*9507f98cSAndroid Build Coastguard Worker void PosixEnv::Schedule(
782*9507f98cSAndroid Build Coastguard Worker     void (*background_work_function)(void* background_work_arg),
783*9507f98cSAndroid Build Coastguard Worker     void* background_work_arg) {
784*9507f98cSAndroid Build Coastguard Worker   background_work_mutex_.Lock();
785*9507f98cSAndroid Build Coastguard Worker 
786*9507f98cSAndroid Build Coastguard Worker   // Start the background thread, if we haven't done so already.
787*9507f98cSAndroid Build Coastguard Worker   if (!started_background_thread_) {
788*9507f98cSAndroid Build Coastguard Worker     started_background_thread_ = true;
789*9507f98cSAndroid Build Coastguard Worker     std::thread background_thread(PosixEnv::BackgroundThreadEntryPoint, this);
790*9507f98cSAndroid Build Coastguard Worker     background_thread.detach();
791*9507f98cSAndroid Build Coastguard Worker   }
792*9507f98cSAndroid Build Coastguard Worker 
793*9507f98cSAndroid Build Coastguard Worker   // If the queue is empty, the background thread may be waiting for work.
794*9507f98cSAndroid Build Coastguard Worker   if (background_work_queue_.empty()) {
795*9507f98cSAndroid Build Coastguard Worker     background_work_cv_.Signal();
796*9507f98cSAndroid Build Coastguard Worker   }
797*9507f98cSAndroid Build Coastguard Worker 
798*9507f98cSAndroid Build Coastguard Worker   background_work_queue_.emplace(background_work_function, background_work_arg);
799*9507f98cSAndroid Build Coastguard Worker   background_work_mutex_.Unlock();
800*9507f98cSAndroid Build Coastguard Worker }
801*9507f98cSAndroid Build Coastguard Worker 
BackgroundThreadMain()802*9507f98cSAndroid Build Coastguard Worker void PosixEnv::BackgroundThreadMain() {
803*9507f98cSAndroid Build Coastguard Worker   while (true) {
804*9507f98cSAndroid Build Coastguard Worker     background_work_mutex_.Lock();
805*9507f98cSAndroid Build Coastguard Worker 
806*9507f98cSAndroid Build Coastguard Worker     // Wait until there is work to be done.
807*9507f98cSAndroid Build Coastguard Worker     while (background_work_queue_.empty()) {
808*9507f98cSAndroid Build Coastguard Worker       background_work_cv_.Wait();
809*9507f98cSAndroid Build Coastguard Worker     }
810*9507f98cSAndroid Build Coastguard Worker 
811*9507f98cSAndroid Build Coastguard Worker     assert(!background_work_queue_.empty());
812*9507f98cSAndroid Build Coastguard Worker     auto background_work_function = background_work_queue_.front().function;
813*9507f98cSAndroid Build Coastguard Worker     void* background_work_arg = background_work_queue_.front().arg;
814*9507f98cSAndroid Build Coastguard Worker     background_work_queue_.pop();
815*9507f98cSAndroid Build Coastguard Worker 
816*9507f98cSAndroid Build Coastguard Worker     background_work_mutex_.Unlock();
817*9507f98cSAndroid Build Coastguard Worker     background_work_function(background_work_arg);
818*9507f98cSAndroid Build Coastguard Worker   }
819*9507f98cSAndroid Build Coastguard Worker }
820*9507f98cSAndroid Build Coastguard Worker 
821*9507f98cSAndroid Build Coastguard Worker namespace {
822*9507f98cSAndroid Build Coastguard Worker 
823*9507f98cSAndroid Build Coastguard Worker // Wraps an Env instance whose destructor is never created.
824*9507f98cSAndroid Build Coastguard Worker //
825*9507f98cSAndroid Build Coastguard Worker // Intended usage:
826*9507f98cSAndroid Build Coastguard Worker //   using PlatformSingletonEnv = SingletonEnv<PlatformEnv>;
827*9507f98cSAndroid Build Coastguard Worker //   void ConfigurePosixEnv(int param) {
828*9507f98cSAndroid Build Coastguard Worker //     PlatformSingletonEnv::AssertEnvNotInitialized();
829*9507f98cSAndroid Build Coastguard Worker //     // set global configuration flags.
830*9507f98cSAndroid Build Coastguard Worker //   }
831*9507f98cSAndroid Build Coastguard Worker //   Env* Env::Default() {
832*9507f98cSAndroid Build Coastguard Worker //     static PlatformSingletonEnv default_env;
833*9507f98cSAndroid Build Coastguard Worker //     return default_env.env();
834*9507f98cSAndroid Build Coastguard Worker //   }
835*9507f98cSAndroid Build Coastguard Worker template <typename EnvType>
836*9507f98cSAndroid Build Coastguard Worker class SingletonEnv {
837*9507f98cSAndroid Build Coastguard Worker  public:
SingletonEnv()838*9507f98cSAndroid Build Coastguard Worker   SingletonEnv() {
839*9507f98cSAndroid Build Coastguard Worker #if !defined(NDEBUG)
840*9507f98cSAndroid Build Coastguard Worker     env_initialized_.store(true, std::memory_order::memory_order_relaxed);
841*9507f98cSAndroid Build Coastguard Worker #endif  // !defined(NDEBUG)
842*9507f98cSAndroid Build Coastguard Worker     static_assert(sizeof(env_storage_) >= sizeof(EnvType),
843*9507f98cSAndroid Build Coastguard Worker                   "env_storage_ will not fit the Env");
844*9507f98cSAndroid Build Coastguard Worker     static_assert(alignof(decltype(env_storage_)) >= alignof(EnvType),
845*9507f98cSAndroid Build Coastguard Worker                   "env_storage_ does not meet the Env's alignment needs");
846*9507f98cSAndroid Build Coastguard Worker     new (&env_storage_) EnvType();
847*9507f98cSAndroid Build Coastguard Worker   }
848*9507f98cSAndroid Build Coastguard Worker   ~SingletonEnv() = default;
849*9507f98cSAndroid Build Coastguard Worker 
850*9507f98cSAndroid Build Coastguard Worker   SingletonEnv(const SingletonEnv&) = delete;
851*9507f98cSAndroid Build Coastguard Worker   SingletonEnv& operator=(const SingletonEnv&) = delete;
852*9507f98cSAndroid Build Coastguard Worker 
env()853*9507f98cSAndroid Build Coastguard Worker   Env* env() { return reinterpret_cast<Env*>(&env_storage_); }
854*9507f98cSAndroid Build Coastguard Worker 
AssertEnvNotInitialized()855*9507f98cSAndroid Build Coastguard Worker   static void AssertEnvNotInitialized() {
856*9507f98cSAndroid Build Coastguard Worker #if !defined(NDEBUG)
857*9507f98cSAndroid Build Coastguard Worker     assert(!env_initialized_.load(std::memory_order::memory_order_relaxed));
858*9507f98cSAndroid Build Coastguard Worker #endif  // !defined(NDEBUG)
859*9507f98cSAndroid Build Coastguard Worker   }
860*9507f98cSAndroid Build Coastguard Worker 
861*9507f98cSAndroid Build Coastguard Worker  private:
862*9507f98cSAndroid Build Coastguard Worker   typename std::aligned_storage<sizeof(EnvType), alignof(EnvType)>::type
863*9507f98cSAndroid Build Coastguard Worker       env_storage_;
864*9507f98cSAndroid Build Coastguard Worker #if !defined(NDEBUG)
865*9507f98cSAndroid Build Coastguard Worker   static std::atomic<bool> env_initialized_;
866*9507f98cSAndroid Build Coastguard Worker #endif  // !defined(NDEBUG)
867*9507f98cSAndroid Build Coastguard Worker };
868*9507f98cSAndroid Build Coastguard Worker 
869*9507f98cSAndroid Build Coastguard Worker #if !defined(NDEBUG)
870*9507f98cSAndroid Build Coastguard Worker template <typename EnvType>
871*9507f98cSAndroid Build Coastguard Worker std::atomic<bool> SingletonEnv<EnvType>::env_initialized_;
872*9507f98cSAndroid Build Coastguard Worker #endif  // !defined(NDEBUG)
873*9507f98cSAndroid Build Coastguard Worker 
874*9507f98cSAndroid Build Coastguard Worker using PosixDefaultEnv = SingletonEnv<PosixEnv>;
875*9507f98cSAndroid Build Coastguard Worker 
876*9507f98cSAndroid Build Coastguard Worker }  // namespace
877*9507f98cSAndroid Build Coastguard Worker 
SetReadOnlyFDLimit(int limit)878*9507f98cSAndroid Build Coastguard Worker void EnvPosixTestHelper::SetReadOnlyFDLimit(int limit) {
879*9507f98cSAndroid Build Coastguard Worker   PosixDefaultEnv::AssertEnvNotInitialized();
880*9507f98cSAndroid Build Coastguard Worker   g_open_read_only_file_limit = limit;
881*9507f98cSAndroid Build Coastguard Worker }
882*9507f98cSAndroid Build Coastguard Worker 
SetReadOnlyMMapLimit(int limit)883*9507f98cSAndroid Build Coastguard Worker void EnvPosixTestHelper::SetReadOnlyMMapLimit(int limit) {
884*9507f98cSAndroid Build Coastguard Worker   PosixDefaultEnv::AssertEnvNotInitialized();
885*9507f98cSAndroid Build Coastguard Worker   g_mmap_limit = limit;
886*9507f98cSAndroid Build Coastguard Worker }
887*9507f98cSAndroid Build Coastguard Worker 
Default()888*9507f98cSAndroid Build Coastguard Worker Env* Env::Default() {
889*9507f98cSAndroid Build Coastguard Worker   static PosixDefaultEnv env_container;
890*9507f98cSAndroid Build Coastguard Worker   return env_container.env();
891*9507f98cSAndroid Build Coastguard Worker }
892*9507f98cSAndroid Build Coastguard Worker 
893*9507f98cSAndroid Build Coastguard Worker }  // namespace leveldb
894