• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 namespace leveldb {
23 
24 class FileLock;
25 class Logger;
26 class RandomAccessFile;
27 class SequentialFile;
28 class Slice;
29 class WritableFile;
30 
31 class Env {
32  public:
Env()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
155 class SequentialFile {
156  public:
SequentialFile()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.
186 class RandomAccessFile {
187  public:
RandomAccessFile()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.
212 class WritableFile {
213  public:
WritableFile()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.
229 class Logger {
230  public:
Logger()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.
245 class FileLock {
246  public:
FileLock()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.
256 extern 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.
263 extern Status WriteStringToFile(Env* env, const Slice& data,
264                                 const std::string& fname);
265 
266 // A utility routine: read contents of named file into *data
267 extern 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.
273 class EnvWrapper : public Env {
274  public:
275   // Initialize an EnvWrapper that delegates all calls to *t
EnvWrapper(Env * t)276   explicit EnvWrapper(Env* t) : target_(t) { }
277   virtual ~EnvWrapper();
278 
279   // Return the target to which this Env forwards all calls
target()280   Env* target() const { return target_; }
281 
282   // The following text is boilerplate that forwards all methods to target()
NewSequentialFile(const std::string & f,SequentialFile ** r)283   Status NewSequentialFile(const std::string& f, SequentialFile** r) {
284     return target_->NewSequentialFile(f, r);
285   }
NewRandomAccessFile(const std::string & f,RandomAccessFile ** r)286   Status NewRandomAccessFile(const std::string& f, RandomAccessFile** r) {
287     return target_->NewRandomAccessFile(f, r);
288   }
NewWritableFile(const std::string & f,WritableFile ** r)289   Status NewWritableFile(const std::string& f, WritableFile** r) {
290     return target_->NewWritableFile(f, r);
291   }
FileExists(const std::string & f)292   bool FileExists(const std::string& f) { return target_->FileExists(f); }
GetChildren(const std::string & dir,std::vector<std::string> * r)293   Status GetChildren(const std::string& dir, std::vector<std::string>* r) {
294     return target_->GetChildren(dir, r);
295   }
DeleteFile(const std::string & f)296   Status DeleteFile(const std::string& f) { return target_->DeleteFile(f); }
CreateDir(const std::string & d)297   Status CreateDir(const std::string& d) { return target_->CreateDir(d); }
DeleteDir(const std::string & d)298   Status DeleteDir(const std::string& d) { return target_->DeleteDir(d); }
GetFileSize(const std::string & f,uint64_t * s)299   Status GetFileSize(const std::string& f, uint64_t* s) {
300     return target_->GetFileSize(f, s);
301   }
RenameFile(const std::string & s,const std::string & t)302   Status RenameFile(const std::string& s, const std::string& t) {
303     return target_->RenameFile(s, t);
304   }
LockFile(const std::string & f,FileLock ** l)305   Status LockFile(const std::string& f, FileLock** l) {
306     return target_->LockFile(f, l);
307   }
UnlockFile(FileLock * l)308   Status UnlockFile(FileLock* l) { return target_->UnlockFile(l); }
Schedule(void (* f)(void *),void * a)309   void Schedule(void (*f)(void*), void* a) {
310     return target_->Schedule(f, a);
311   }
StartThread(void (* f)(void *),void * a)312   void StartThread(void (*f)(void*), void* a) {
313     return target_->StartThread(f, a);
314   }
GetTestDirectory(std::string * path)315   virtual Status GetTestDirectory(std::string* path) {
316     return target_->GetTestDirectory(path);
317   }
NewLogger(const std::string & fname,Logger ** result)318   virtual Status NewLogger(const std::string& fname, Logger** result) {
319     return target_->NewLogger(fname, result);
320   }
NowMicros()321   uint64_t NowMicros() {
322     return target_->NowMicros();
323   }
SleepForMicroseconds(int micros)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