1 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
4 | // |
5 | // An Env is an interface used by the leveldb implementation to access |
6 | // operating system functionality like the filesystem etc. Callers |
7 | // may wish to provide a custom Env object when opening a database to |
8 | // get fine gain control; e.g., to rate limit file system operations. |
9 | // |
10 | // All Env implementations are safe for concurrent access from |
11 | // multiple threads without any external synchronization. |
12 | |
13 | #ifndef STORAGE_LEVELDB_INCLUDE_ENV_H_ |
14 | #define STORAGE_LEVELDB_INCLUDE_ENV_H_ |
15 | |
16 | #include <cstdarg> |
17 | #include <cstdint> |
18 | #include <string> |
19 | #include <vector> |
20 | |
21 | #include "leveldb/export.h" |
22 | #include "leveldb/status.h" |
23 | |
24 | // This workaround can be removed when leveldb::Env::DeleteFile is removed. |
25 | #if defined(_WIN32) |
26 | // On Windows, the method name DeleteFile (below) introduces the risk of |
27 | // triggering undefined behavior by exposing the compiler to different |
28 | // declarations of the Env class in different translation units. |
29 | // |
30 | // This is because <windows.h>, a fairly popular header file for Windows |
31 | // applications, defines a DeleteFile macro. So, files that include the Windows |
32 | // header before this header will contain an altered Env declaration. |
33 | // |
34 | // This workaround ensures that the compiler sees the same Env declaration, |
35 | // independently of whether <windows.h> was included. |
36 | #if defined(DeleteFile) |
37 | #undef DeleteFile |
38 | #define LEVELDB_DELETEFILE_UNDEFINED |
39 | #endif // defined(DeleteFile) |
40 | #endif // defined(_WIN32) |
41 | |
42 | namespace leveldb { |
43 | |
44 | class FileLock; |
45 | class Logger; |
46 | class RandomAccessFile; |
47 | class SequentialFile; |
48 | class Slice; |
49 | class WritableFile; |
50 | |
51 | class LEVELDB_EXPORT Env { |
52 | public: |
53 | Env(); |
54 | |
55 | Env(const Env&) = delete; |
56 | Env& operator=(const Env&) = delete; |
57 | |
58 | virtual ~Env(); |
59 | |
60 | // Return a default environment suitable for the current operating |
61 | // system. Sophisticated users may wish to provide their own Env |
62 | // implementation instead of relying on this default environment. |
63 | // |
64 | // The result of Default() belongs to leveldb and must never be deleted. |
65 | static Env* Default(); |
66 | |
67 | // Create an object that sequentially reads the file with the specified name. |
68 | // On success, stores a pointer to the new file in *result and returns OK. |
69 | // On failure stores nullptr in *result and returns non-OK. If the file does |
70 | // not exist, returns a non-OK status. Implementations should return a |
71 | // NotFound status when the file does not exist. |
72 | // |
73 | // The returned file will only be accessed by one thread at a time. |
74 | virtual Status NewSequentialFile(const std::string& fname, |
75 | SequentialFile** result) = 0; |
76 | |
77 | // Create an object supporting random-access reads from the file with the |
78 | // specified name. On success, stores a pointer to the new file in |
79 | // *result and returns OK. On failure stores nullptr in *result and |
80 | // returns non-OK. If the file does not exist, returns a non-OK |
81 | // status. Implementations should return a NotFound status when the file does |
82 | // not exist. |
83 | // |
84 | // The returned file may be concurrently accessed by multiple threads. |
85 | virtual Status NewRandomAccessFile(const std::string& fname, |
86 | RandomAccessFile** result) = 0; |
87 | |
88 | // Create an object that writes to a new file with the specified |
89 | // name. Deletes any existing file with the same name and creates a |
90 | // new file. On success, stores a pointer to the new file in |
91 | // *result and returns OK. On failure stores nullptr in *result and |
92 | // returns non-OK. |
93 | // |
94 | // The returned file will only be accessed by one thread at a time. |
95 | virtual Status NewWritableFile(const std::string& fname, |
96 | WritableFile** result) = 0; |
97 | |
98 | // Create an object that either appends to an existing file, or |
99 | // writes to a new file (if the file does not exist to begin with). |
100 | // On success, stores a pointer to the new file in *result and |
101 | // returns OK. On failure stores nullptr in *result and returns |
102 | // non-OK. |
103 | // |
104 | // The returned file will only be accessed by one thread at a time. |
105 | // |
106 | // May return an IsNotSupportedError error if this Env does |
107 | // not allow appending to an existing file. Users of Env (including |
108 | // the leveldb implementation) must be prepared to deal with |
109 | // an Env that does not support appending. |
110 | virtual Status NewAppendableFile(const std::string& fname, |
111 | WritableFile** result); |
112 | |
113 | // Returns true iff the named file exists. |
114 | virtual bool FileExists(const std::string& fname) = 0; |
115 | |
116 | // Store in *result the names of the children of the specified directory. |
117 | // The names are relative to "dir". |
118 | // Original contents of *results are dropped. |
119 | virtual Status GetChildren(const std::string& dir, |
120 | std::vector<std::string>* result) = 0; |
121 | // Delete the named file. |
122 | // |
123 | // The default implementation calls DeleteFile, to support legacy Env |
124 | // implementations. Updated Env implementations must override RemoveFile and |
125 | // ignore the existence of DeleteFile. Updated code calling into the Env API |
126 | // must call RemoveFile instead of DeleteFile. |
127 | // |
128 | // A future release will remove DeleteDir and the default implementation of |
129 | // RemoveDir. |
130 | virtual Status RemoveFile(const std::string& fname); |
131 | |
132 | // DEPRECATED: Modern Env implementations should override RemoveFile instead. |
133 | // |
134 | // The default implementation calls RemoveFile, to support legacy Env user |
135 | // code that calls this method on modern Env implementations. Modern Env user |
136 | // code should call RemoveFile. |
137 | // |
138 | // A future release will remove this method. |
139 | virtual Status DeleteFile(const std::string& fname); |
140 | |
141 | // Create the specified directory. |
142 | virtual Status CreateDir(const std::string& dirname) = 0; |
143 | |
144 | // Delete the specified directory. |
145 | // |
146 | // The default implementation calls DeleteDir, to support legacy Env |
147 | // implementations. Updated Env implementations must override RemoveDir and |
148 | // ignore the existence of DeleteDir. Modern code calling into the Env API |
149 | // must call RemoveDir instead of DeleteDir. |
150 | // |
151 | // A future release will remove DeleteDir and the default implementation of |
152 | // RemoveDir. |
153 | virtual Status RemoveDir(const std::string& dirname); |
154 | |
155 | // DEPRECATED: Modern Env implementations should override RemoveDir instead. |
156 | // |
157 | // The default implementation calls RemoveDir, to support legacy Env user |
158 | // code that calls this method on modern Env implementations. Modern Env user |
159 | // code should call RemoveDir. |
160 | // |
161 | // A future release will remove this method. |
162 | virtual Status DeleteDir(const std::string& dirname); |
163 | |
164 | // Store the size of fname in *file_size. |
165 | virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) = 0; |
166 | |
167 | // Rename file src to target. |
168 | virtual Status RenameFile(const std::string& src, |
169 | const std::string& target) = 0; |
170 | |
171 | // Lock the specified file. Used to prevent concurrent access to |
172 | // the same db by multiple processes. On failure, stores nullptr in |
173 | // *lock and returns non-OK. |
174 | // |
175 | // On success, stores a pointer to the object that represents the |
176 | // acquired lock in *lock and returns OK. The caller should call |
177 | // UnlockFile(*lock) to release the lock. If the process exits, |
178 | // the lock will be automatically released. |
179 | // |
180 | // If somebody else already holds the lock, finishes immediately |
181 | // with a failure. I.e., this call does not wait for existing locks |
182 | // to go away. |
183 | // |
184 | // May create the named file if it does not already exist. |
185 | virtual Status LockFile(const std::string& fname, FileLock** lock) = 0; |
186 | |
187 | // Release the lock acquired by a previous successful call to LockFile. |
188 | // REQUIRES: lock was returned by a successful LockFile() call |
189 | // REQUIRES: lock has not already been unlocked. |
190 | virtual Status UnlockFile(FileLock* lock) = 0; |
191 | |
192 | // Arrange to run "(*function)(arg)" once in a background thread. |
193 | // |
194 | // "function" may run in an unspecified thread. Multiple functions |
195 | // added to the same Env may run concurrently in different threads. |
196 | // I.e., the caller may not assume that background work items are |
197 | // serialized. |
198 | virtual void Schedule(void (*function)(void* arg), void* arg) = 0; |
199 | |
200 | // Start a new thread, invoking "function(arg)" within the new thread. |
201 | // When "function(arg)" returns, the thread will be destroyed. |
202 | virtual void StartThread(void (*function)(void* arg), void* arg) = 0; |
203 | |
204 | // *path is set to a temporary directory that can be used for testing. It may |
205 | // or may not have just been created. The directory may or may not differ |
206 | // between runs of the same process, but subsequent calls will return the |
207 | // same directory. |
208 | virtual Status GetTestDirectory(std::string* path) = 0; |
209 | |
210 | // Create and return a log file for storing informational messages. |
211 | virtual Status NewLogger(const std::string& fname, Logger** result) = 0; |
212 | |
213 | // Returns the number of micro-seconds since some fixed point in time. Only |
214 | // useful for computing deltas of time. |
215 | virtual uint64_t NowMicros() = 0; |
216 | |
217 | // Sleep/delay the thread for the prescribed number of micro-seconds. |
218 | virtual void SleepForMicroseconds(int micros) = 0; |
219 | }; |
220 | |
221 | // A file abstraction for reading sequentially through a file |
222 | class LEVELDB_EXPORT SequentialFile { |
223 | public: |
224 | SequentialFile() = default; |
225 | |
226 | SequentialFile(const SequentialFile&) = delete; |
227 | SequentialFile& operator=(const SequentialFile&) = delete; |
228 | |
229 | virtual ~SequentialFile(); |
230 | |
231 | // Read up to "n" bytes from the file. "scratch[0..n-1]" may be |
232 | // written by this routine. Sets "*result" to the data that was |
233 | // read (including if fewer than "n" bytes were successfully read). |
234 | // May set "*result" to point at data in "scratch[0..n-1]", so |
235 | // "scratch[0..n-1]" must be live when "*result" is used. |
236 | // If an error was encountered, returns a non-OK status. |
237 | // |
238 | // REQUIRES: External synchronization |
239 | virtual Status Read(size_t n, Slice* result, char* scratch) = 0; |
240 | |
241 | // Skip "n" bytes from the file. This is guaranteed to be no |
242 | // slower that reading the same data, but may be faster. |
243 | // |
244 | // If end of file is reached, skipping will stop at the end of the |
245 | // file, and Skip will return OK. |
246 | // |
247 | // REQUIRES: External synchronization |
248 | virtual Status Skip(uint64_t n) = 0; |
249 | }; |
250 | |
251 | // A file abstraction for randomly reading the contents of a file. |
252 | class LEVELDB_EXPORT RandomAccessFile { |
253 | public: |
254 | RandomAccessFile() = default; |
255 | |
256 | RandomAccessFile(const RandomAccessFile&) = delete; |
257 | RandomAccessFile& operator=(const RandomAccessFile&) = delete; |
258 | |
259 | virtual ~RandomAccessFile(); |
260 | |
261 | // Read up to "n" bytes from the file starting at "offset". |
262 | // "scratch[0..n-1]" may be written by this routine. Sets "*result" |
263 | // to the data that was read (including if fewer than "n" bytes were |
264 | // successfully read). May set "*result" to point at data in |
265 | // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when |
266 | // "*result" is used. If an error was encountered, returns a non-OK |
267 | // status. |
268 | // |
269 | // Safe for concurrent use by multiple threads. |
270 | virtual Status Read(uint64_t offset, size_t n, Slice* result, |
271 | char* scratch) const = 0; |
272 | }; |
273 | |
274 | // A file abstraction for sequential writing. The implementation |
275 | // must provide buffering since callers may append small fragments |
276 | // at a time to the file. |
277 | class LEVELDB_EXPORT WritableFile { |
278 | public: |
279 | WritableFile() = default; |
280 | |
281 | WritableFile(const WritableFile&) = delete; |
282 | WritableFile& operator=(const WritableFile&) = delete; |
283 | |
284 | virtual ~WritableFile(); |
285 | |
286 | virtual Status Append(const Slice& data) = 0; |
287 | virtual Status Close() = 0; |
288 | virtual Status Flush() = 0; |
289 | virtual Status Sync() = 0; |
290 | }; |
291 | |
292 | // An interface for writing log messages. |
293 | class LEVELDB_EXPORT Logger { |
294 | public: |
295 | Logger() = default; |
296 | |
297 | Logger(const Logger&) = delete; |
298 | Logger& operator=(const Logger&) = delete; |
299 | |
300 | virtual ~Logger(); |
301 | |
302 | // Write an entry to the log file with the specified format. |
303 | virtual void Logv(const char* format, std::va_list ap) = 0; |
304 | }; |
305 | |
306 | // Identifies a locked file. |
307 | class LEVELDB_EXPORT FileLock { |
308 | public: |
309 | FileLock() = default; |
310 | |
311 | FileLock(const FileLock&) = delete; |
312 | FileLock& operator=(const FileLock&) = delete; |
313 | |
314 | virtual ~FileLock(); |
315 | }; |
316 | |
317 | // Log the specified data to *info_log if info_log is non-null. |
318 | void Log(Logger* info_log, const char* format, ...) |
319 | #if defined(__GNUC__) || defined(__clang__) |
320 | __attribute__((__format__(__printf__, 2, 3))) |
321 | #endif |
322 | ; |
323 | |
324 | // A utility routine: write "data" to the named file. |
325 | LEVELDB_EXPORT Status WriteStringToFile(Env* env, const Slice& data, |
326 | const std::string& fname); |
327 | |
328 | // A utility routine: read contents of named file into *data |
329 | LEVELDB_EXPORT Status ReadFileToString(Env* env, const std::string& fname, |
330 | std::string* data); |
331 | |
332 | // An implementation of Env that forwards all calls to another Env. |
333 | // May be useful to clients who wish to override just part of the |
334 | // functionality of another Env. |
335 | class LEVELDB_EXPORT EnvWrapper : public Env { |
336 | public: |
337 | // Initialize an EnvWrapper that delegates all calls to *t. |
338 | explicit EnvWrapper(Env* t) : target_(t) {} |
339 | virtual ~EnvWrapper(); |
340 | |
341 | // Return the target to which this Env forwards all calls. |
342 | Env* target() const { return target_; } |
343 | |
344 | // The following text is boilerplate that forwards all methods to target(). |
345 | Status NewSequentialFile(const std::string& f, SequentialFile** r) override { |
346 | return target_->NewSequentialFile(f, r); |
347 | } |
348 | Status NewRandomAccessFile(const std::string& f, |
349 | RandomAccessFile** r) override { |
350 | return target_->NewRandomAccessFile(f, r); |
351 | } |
352 | Status NewWritableFile(const std::string& f, WritableFile** r) override { |
353 | return target_->NewWritableFile(f, r); |
354 | } |
355 | Status NewAppendableFile(const std::string& f, WritableFile** r) override { |
356 | return target_->NewAppendableFile(f, r); |
357 | } |
358 | bool FileExists(const std::string& f) override { |
359 | return target_->FileExists(f); |
360 | } |
361 | Status GetChildren(const std::string& dir, |
362 | std::vector<std::string>* r) override { |
363 | return target_->GetChildren(dir, r); |
364 | } |
365 | Status RemoveFile(const std::string& f) override { |
366 | return target_->RemoveFile(f); |
367 | } |
368 | Status CreateDir(const std::string& d) override { |
369 | return target_->CreateDir(d); |
370 | } |
371 | Status RemoveDir(const std::string& d) override { |
372 | return target_->RemoveDir(d); |
373 | } |
374 | Status GetFileSize(const std::string& f, uint64_t* s) override { |
375 | return target_->GetFileSize(f, s); |
376 | } |
377 | Status RenameFile(const std::string& s, const std::string& t) override { |
378 | return target_->RenameFile(s, t); |
379 | } |
380 | Status LockFile(const std::string& f, FileLock** l) override { |
381 | return target_->LockFile(f, l); |
382 | } |
383 | Status UnlockFile(FileLock* l) override { return target_->UnlockFile(l); } |
384 | void Schedule(void (*f)(void*), void* a) override { |
385 | return target_->Schedule(f, a); |
386 | } |
387 | void StartThread(void (*f)(void*), void* a) override { |
388 | return target_->StartThread(f, a); |
389 | } |
390 | Status GetTestDirectory(std::string* path) override { |
391 | return target_->GetTestDirectory(path); |
392 | } |
393 | Status NewLogger(const std::string& fname, Logger** result) override { |
394 | return target_->NewLogger(fname, result); |
395 | } |
396 | uint64_t NowMicros() override { return target_->NowMicros(); } |
397 | void SleepForMicroseconds(int micros) override { |
398 | target_->SleepForMicroseconds(micros); |
399 | } |
400 | |
401 | private: |
402 | Env* target_; |
403 | }; |
404 | |
405 | } // namespace leveldb |
406 | |
407 | // This workaround can be removed when leveldb::Env::DeleteFile is removed. |
408 | // Redefine DeleteFile if it was undefined earlier. |
409 | #if defined(_WIN32) && defined(LEVELDB_DELETEFILE_UNDEFINED) |
410 | #if defined(UNICODE) |
411 | #define DeleteFile DeleteFileW |
412 | #else |
413 | #define DeleteFile DeleteFileA |
414 | #endif // defined(UNICODE) |
415 | #endif // defined(_WIN32) && defined(LEVELDB_DELETEFILE_UNDEFINED) |
416 | |
417 | #endif // STORAGE_LEVELDB_INCLUDE_ENV_H_ |
418 | |