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