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