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 42 namespace leveldb { 43 44 class FileLock; 45 class Logger; 46 class RandomAccessFile; 47 class SequentialFile; 48 class Slice; 49 class WritableFile; 50 51 class 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 222 class 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. 252 class 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. 277 class 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. 293 class 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. 307 class 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. 318 void 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. 325 LEVELDB_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 329 LEVELDB_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. 335 class LEVELDB_EXPORT EnvWrapper : public Env { 336 public: 337 // Initialize an EnvWrapper that delegates all calls to *t. EnvWrapper(Env * t)338 explicit EnvWrapper(Env* t) : target_(t) {} 339 virtual ~EnvWrapper(); 340 341 // Return the target to which this Env forwards all calls. target()342 Env* target() const { return target_; } 343 344 // The following text is boilerplate that forwards all methods to target(). NewSequentialFile(const std::string & f,SequentialFile ** r)345 Status NewSequentialFile(const std::string& f, SequentialFile** r) override { 346 return target_->NewSequentialFile(f, r); 347 } NewRandomAccessFile(const std::string & f,RandomAccessFile ** r)348 Status NewRandomAccessFile(const std::string& f, 349 RandomAccessFile** r) override { 350 return target_->NewRandomAccessFile(f, r); 351 } NewWritableFile(const std::string & f,WritableFile ** r)352 Status NewWritableFile(const std::string& f, WritableFile** r) override { 353 return target_->NewWritableFile(f, r); 354 } NewAppendableFile(const std::string & f,WritableFile ** r)355 Status NewAppendableFile(const std::string& f, WritableFile** r) override { 356 return target_->NewAppendableFile(f, r); 357 } FileExists(const std::string & f)358 bool FileExists(const std::string& f) override { 359 return target_->FileExists(f); 360 } GetChildren(const std::string & dir,std::vector<std::string> * r)361 Status GetChildren(const std::string& dir, 362 std::vector<std::string>* r) override { 363 return target_->GetChildren(dir, r); 364 } RemoveFile(const std::string & f)365 Status RemoveFile(const std::string& f) override { 366 return target_->RemoveFile(f); 367 } CreateDir(const std::string & d)368 Status CreateDir(const std::string& d) override { 369 return target_->CreateDir(d); 370 } RemoveDir(const std::string & d)371 Status RemoveDir(const std::string& d) override { 372 return target_->RemoveDir(d); 373 } GetFileSize(const std::string & f,uint64_t * s)374 Status GetFileSize(const std::string& f, uint64_t* s) override { 375 return target_->GetFileSize(f, s); 376 } RenameFile(const std::string & s,const std::string & t)377 Status RenameFile(const std::string& s, const std::string& t) override { 378 return target_->RenameFile(s, t); 379 } LockFile(const std::string & f,FileLock ** l)380 Status LockFile(const std::string& f, FileLock** l) override { 381 return target_->LockFile(f, l); 382 } UnlockFile(FileLock * l)383 Status UnlockFile(FileLock* l) override { return target_->UnlockFile(l); } Schedule(void (* f)(void *),void * a)384 void Schedule(void (*f)(void*), void* a) override { 385 return target_->Schedule(f, a); 386 } StartThread(void (* f)(void *),void * a)387 void StartThread(void (*f)(void*), void* a) override { 388 return target_->StartThread(f, a); 389 } GetTestDirectory(std::string * path)390 Status GetTestDirectory(std::string* path) override { 391 return target_->GetTestDirectory(path); 392 } NewLogger(const std::string & fname,Logger ** result)393 Status NewLogger(const std::string& fname, Logger** result) override { 394 return target_->NewLogger(fname, result); 395 } NowMicros()396 uint64_t NowMicros() override { return target_->NowMicros(); } SleepForMicroseconds(int micros)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