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
42namespace leveldb {
43
44class FileLock;
45class Logger;
46class RandomAccessFile;
47class SequentialFile;
48class Slice;
49class WritableFile;
50
51class 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
222class 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.
252class 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.
277class 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.
293class 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.
307class 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.
318void 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.
325LEVELDB_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
329LEVELDB_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.
335class 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