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 <string>
17#include <vector>
18#include <stdarg.h>
19#include <stdint.h>
20#include "leveldb/status.h"
21
22namespace leveldb {
23
24class FileLock;
25class Logger;
26class RandomAccessFile;
27class SequentialFile;
28class Slice;
29class WritableFile;
30
31class Env {
32 public:
33  Env() { }
34  virtual ~Env();
35
36  // Return a default environment suitable for the current operating
37  // system.  Sophisticated users may wish to provide their own Env
38  // implementation instead of relying on this default environment.
39  //
40  // The result of Default() belongs to leveldb and must never be deleted.
41  static Env* Default();
42
43  // Create a brand new sequentially-readable file with the specified name.
44  // On success, stores a pointer to the new file in *result and returns OK.
45  // On failure stores NULL in *result and returns non-OK.  If the file does
46  // not exist, returns a non-OK status.
47  //
48  // The returned file will only be accessed by one thread at a time.
49  virtual Status NewSequentialFile(const std::string& fname,
50                                   SequentialFile** result) = 0;
51
52  // Create a brand new random access read-only file with the
53  // specified name.  On success, stores a pointer to the new file in
54  // *result and returns OK.  On failure stores NULL in *result and
55  // returns non-OK.  If the file does not exist, returns a non-OK
56  // status.
57  //
58  // The returned file may be concurrently accessed by multiple threads.
59  virtual Status NewRandomAccessFile(const std::string& fname,
60                                     RandomAccessFile** result) = 0;
61
62  // Create an object that writes to a new file with the specified
63  // name.  Deletes any existing file with the same name and creates a
64  // new file.  On success, stores a pointer to the new file in
65  // *result and returns OK.  On failure stores NULL in *result and
66  // returns non-OK.
67  //
68  // The returned file will only be accessed by one thread at a time.
69  virtual Status NewWritableFile(const std::string& fname,
70                                 WritableFile** result) = 0;
71
72  // Returns true iff the named file exists.
73  virtual bool FileExists(const std::string& fname) = 0;
74
75  // Store in *result the names of the children of the specified directory.
76  // The names are relative to "dir".
77  // Original contents of *results are dropped.
78  virtual Status GetChildren(const std::string& dir,
79                             std::vector<std::string>* result) = 0;
80
81  // Delete the named file.
82  virtual Status DeleteFile(const std::string& fname) = 0;
83
84  // Create the specified directory.
85  virtual Status CreateDir(const std::string& dirname) = 0;
86
87  // Delete the specified directory.
88  virtual Status DeleteDir(const std::string& dirname) = 0;
89
90  // Store the size of fname in *file_size.
91  virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) = 0;
92
93  // Rename file src to target.
94  virtual Status RenameFile(const std::string& src,
95                            const std::string& target) = 0;
96
97  // Lock the specified file.  Used to prevent concurrent access to
98  // the same db by multiple processes.  On failure, stores NULL in
99  // *lock and returns non-OK.
100  //
101  // On success, stores a pointer to the object that represents the
102  // acquired lock in *lock and returns OK.  The caller should call
103  // UnlockFile(*lock) to release the lock.  If the process exits,
104  // the lock will be automatically released.
105  //
106  // If somebody else already holds the lock, finishes immediately
107  // with a failure.  I.e., this call does not wait for existing locks
108  // to go away.
109  //
110  // May create the named file if it does not already exist.
111  virtual Status LockFile(const std::string& fname, FileLock** lock) = 0;
112
113  // Release the lock acquired by a previous successful call to LockFile.
114  // REQUIRES: lock was returned by a successful LockFile() call
115  // REQUIRES: lock has not already been unlocked.
116  virtual Status UnlockFile(FileLock* lock) = 0;
117
118  // Arrange to run "(*function)(arg)" once in a background thread.
119  //
120  // "function" may run in an unspecified thread.  Multiple functions
121  // added to the same Env may run concurrently in different threads.
122  // I.e., the caller may not assume that background work items are
123  // serialized.
124  virtual void Schedule(
125      void (*function)(void* arg),
126      void* arg) = 0;
127
128  // Start a new thread, invoking "function(arg)" within the new thread.
129  // When "function(arg)" returns, the thread will be destroyed.
130  virtual void StartThread(void (*function)(void* arg), void* arg) = 0;
131
132  // *path is set to a temporary directory that can be used for testing. It may
133  // or many not have just been created. The directory may or may not differ
134  // between runs of the same process, but subsequent calls will return the
135  // same directory.
136  virtual Status GetTestDirectory(std::string* path) = 0;
137
138  // Create and return a log file for storing informational messages.
139  virtual Status NewLogger(const std::string& fname, Logger** result) = 0;
140
141  // Returns the number of micro-seconds since some fixed point in time. Only
142  // useful for computing deltas of time.
143  virtual uint64_t NowMicros() = 0;
144
145  // Sleep/delay the thread for the perscribed number of micro-seconds.
146  virtual void SleepForMicroseconds(int micros) = 0;
147
148 private:
149  // No copying allowed
150  Env(const Env&);
151  void operator=(const Env&);
152};
153
154// A file abstraction for reading sequentially through a file
155class SequentialFile {
156 public:
157  SequentialFile() { }
158  virtual ~SequentialFile();
159
160  // Read up to "n" bytes from the file.  "scratch[0..n-1]" may be
161  // written by this routine.  Sets "*result" to the data that was
162  // read (including if fewer than "n" bytes were successfully read).
163  // May set "*result" to point at data in "scratch[0..n-1]", so
164  // "scratch[0..n-1]" must be live when "*result" is used.
165  // If an error was encountered, returns a non-OK status.
166  //
167  // REQUIRES: External synchronization
168  virtual Status Read(size_t n, Slice* result, char* scratch) = 0;
169
170  // Skip "n" bytes from the file. This is guaranteed to be no
171  // slower that reading the same data, but may be faster.
172  //
173  // If end of file is reached, skipping will stop at the end of the
174  // file, and Skip will return OK.
175  //
176  // REQUIRES: External synchronization
177  virtual Status Skip(uint64_t n) = 0;
178
179 private:
180  // No copying allowed
181  SequentialFile(const SequentialFile&);
182  void operator=(const SequentialFile&);
183};
184
185// A file abstraction for randomly reading the contents of a file.
186class RandomAccessFile {
187 public:
188  RandomAccessFile() { }
189  virtual ~RandomAccessFile();
190
191  // Read up to "n" bytes from the file starting at "offset".
192  // "scratch[0..n-1]" may be written by this routine.  Sets "*result"
193  // to the data that was read (including if fewer than "n" bytes were
194  // successfully read).  May set "*result" to point at data in
195  // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when
196  // "*result" is used.  If an error was encountered, returns a non-OK
197  // status.
198  //
199  // Safe for concurrent use by multiple threads.
200  virtual Status Read(uint64_t offset, size_t n, Slice* result,
201                      char* scratch) const = 0;
202
203 private:
204  // No copying allowed
205  RandomAccessFile(const RandomAccessFile&);
206  void operator=(const RandomAccessFile&);
207};
208
209// A file abstraction for sequential writing.  The implementation
210// must provide buffering since callers may append small fragments
211// at a time to the file.
212class WritableFile {
213 public:
214  WritableFile() { }
215  virtual ~WritableFile();
216
217  virtual Status Append(const Slice& data) = 0;
218  virtual Status Close() = 0;
219  virtual Status Flush() = 0;
220  virtual Status Sync() = 0;
221
222 private:
223  // No copying allowed
224  WritableFile(const WritableFile&);
225  void operator=(const WritableFile&);
226};
227
228// An interface for writing log messages.
229class Logger {
230 public:
231  Logger() { }
232  virtual ~Logger();
233
234  // Write an entry to the log file with the specified format.
235  virtual void Logv(const char* format, va_list ap) = 0;
236
237 private:
238  // No copying allowed
239  Logger(const Logger&);
240  void operator=(const Logger&);
241};
242
243
244// Identifies a locked file.
245class FileLock {
246 public:
247  FileLock() { }
248  virtual ~FileLock();
249 private:
250  // No copying allowed
251  FileLock(const FileLock&);
252  void operator=(const FileLock&);
253};
254
255// Log the specified data to *info_log if info_log is non-NULL.
256extern void Log(Logger* info_log, const char* format, ...)
257#   if defined(__GNUC__) || defined(__clang__)
258    __attribute__((__format__ (__printf__, 2, 3)))
259#   endif
260    ;
261
262// A utility routine: write "data" to the named file.
263extern Status WriteStringToFile(Env* env, const Slice& data,
264                                const std::string& fname);
265
266// A utility routine: read contents of named file into *data
267extern Status ReadFileToString(Env* env, const std::string& fname,
268                               std::string* data);
269
270// An implementation of Env that forwards all calls to another Env.
271// May be useful to clients who wish to override just part of the
272// functionality of another Env.
273class EnvWrapper : public Env {
274 public:
275  // Initialize an EnvWrapper that delegates all calls to *t
276  explicit EnvWrapper(Env* t) : target_(t) { }
277  virtual ~EnvWrapper();
278
279  // Return the target to which this Env forwards all calls
280  Env* target() const { return target_; }
281
282  // The following text is boilerplate that forwards all methods to target()
283  Status NewSequentialFile(const std::string& f, SequentialFile** r) {
284    return target_->NewSequentialFile(f, r);
285  }
286  Status NewRandomAccessFile(const std::string& f, RandomAccessFile** r) {
287    return target_->NewRandomAccessFile(f, r);
288  }
289  Status NewWritableFile(const std::string& f, WritableFile** r) {
290    return target_->NewWritableFile(f, r);
291  }
292  bool FileExists(const std::string& f) { return target_->FileExists(f); }
293  Status GetChildren(const std::string& dir, std::vector<std::string>* r) {
294    return target_->GetChildren(dir, r);
295  }
296  Status DeleteFile(const std::string& f) { return target_->DeleteFile(f); }
297  Status CreateDir(const std::string& d) { return target_->CreateDir(d); }
298  Status DeleteDir(const std::string& d) { return target_->DeleteDir(d); }
299  Status GetFileSize(const std::string& f, uint64_t* s) {
300    return target_->GetFileSize(f, s);
301  }
302  Status RenameFile(const std::string& s, const std::string& t) {
303    return target_->RenameFile(s, t);
304  }
305  Status LockFile(const std::string& f, FileLock** l) {
306    return target_->LockFile(f, l);
307  }
308  Status UnlockFile(FileLock* l) { return target_->UnlockFile(l); }
309  void Schedule(void (*f)(void*), void* a) {
310    return target_->Schedule(f, a);
311  }
312  void StartThread(void (*f)(void*), void* a) {
313    return target_->StartThread(f, a);
314  }
315  virtual Status GetTestDirectory(std::string* path) {
316    return target_->GetTestDirectory(path);
317  }
318  virtual Status NewLogger(const std::string& fname, Logger** result) {
319    return target_->NewLogger(fname, result);
320  }
321  uint64_t NowMicros() {
322    return target_->NowMicros();
323  }
324  void SleepForMicroseconds(int micros) {
325    target_->SleepForMicroseconds(micros);
326  }
327 private:
328  Env* target_;
329};
330
331}  // namespace leveldb
332
333#endif  // STORAGE_LEVELDB_INCLUDE_ENV_H_
334